IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage SQL Discussion :

Insertion dans une table relationnelle


Sujet :

Langage SQL

  1. #1
    Membre régulier
    Inscrit en
    Juillet 2004
    Messages
    306
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 306
    Points : 122
    Points
    122
    Par défaut Insertion dans une table relationnelle
    Bonjour,

    j'utilise Postgresql.
    je possède une bdd avec deux tables produit et commande et une table relationnelle produit_commande.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    table t_produit (
       cli_Id integer,
       cli_Libelle varchar(32)
    );
     
    table t_commande (
       cmd_Id integer auto_increment,
       cmd_Date date
    );
     
    table r_prod_cmd (
       cmd_Id integer,
       prod_Id integer,
       qute integer,
       remise integer
    );
    J'aimerais développé un formulaire qui permet de saisir de nouvelle commandes. La clef de la table commande est auto-incrementée. J'utilise pour cela l'astuce fournit par SQLPro, l'utilisation d'une autre table possédant les valeurs des clefs.
    Ainsi, mon formulaire consiste à choisir les produits rattachés à la commande. Une fois que l'utilisateur valide, le script php doit permettre de remplir la table commande et la table relationnelle.
    Ma difficulté est de remplir la table relationnelle r_prod_cmd. Je dois connaître l'id de la commande crée, mais celui-ci est auto-incrementé. Donc depuis mon script je ne peux le connaître. A moins qu'il y ait une solution.
    Je ne peux donc exécuter séparément, l'insertion à la table commande et l'insertion à la table relationnelle. Dois-je créer une procédure stockée qui gère l'ajout de nouvelles commandes ?

    Merci pour votre aide.

    ++

  2. #2
    Membre régulier
    Inscrit en
    Juillet 2004
    Messages
    306
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 306
    Points : 122
    Points
    122
    Par défaut
    Snif, Snif pas de réponse.
    Je m'étais dit que cela devait être un problème rencontré fréquemment.

    ++

  3. #3
    Membre expert
    Avatar de TheLeadingEdge
    Inscrit en
    Mai 2005
    Messages
    1 199
    Détails du profil
    Informations forums :
    Inscription : Mai 2005
    Messages : 1 199
    Points : 3 103
    Points
    3 103
    Par défaut
    Bonjour,

    Il faudrait en savoir plus sur le fonctionnement de ton appli. pour te conseiller. A priori, comme ça, je te proposerais de mémoriser ttes tes lignes de commandes et de n'enregistrer le tout (n° de commande, commande et lignes, maj des stocks éventuellement etc...) en 1 seule fois dans une transaction que lorsque ton utilisateur valide sa commande.

    A +

  4. #4
    Membre régulier
    Inscrit en
    Juillet 2004
    Messages
    306
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 306
    Points : 122
    Points
    122
    Par défaut
    Bonjour,

    A priori, comme ça, je te proposerais de mémoriser ttes tes lignes de commandes et de n'enregistrer le tout (n° de commande, commande et lignes, maj des stocks éventuellement etc...) en 1 seule fois dans une transaction que lorsque ton utilisateur valide sa commande
    Oui j'aimerais bien faire ainsi. Mais:

    Une nouvelle commande est crée. Est alors ajouté à la table t_commande, la date de la commande. Le numéro de commande lui est automatiquement généré. En effet, sur un trigger insertion, une fonction est appelée et génère automatiquement, un nouveau numéro de commande en incrémentant de 1 le dernier numéro ajouté et en concaténant le numéro obtenu avec la chaîne 'COM'.
    Ainsi, j'ai crée mon numéro de commande.
    Mais voilà, ensuite, pour insérer dans la table relationnelle, la liste des produits se rapportant à la commande, je dois connaître le numéro de commande.
    Je m'étais dit que ce problème était connu, ou avais déjà été rencontré. Comment faites-vous dans ce cas, pour insérer dans une table relationnelle un id généré automatiquement ?
    Il faut développer une procedure stockée, qui gère toute la transaction ?

    Merci pour votre aide.
    ++

  5. #5
    Expert confirmé

    Profil pro
    Inscrit en
    Avril 2002
    Messages
    3 338
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Avril 2002
    Messages : 3 338
    Points : 4 657
    Points
    4 657
    Par défaut
    Citation Envoyé par etiennegaloup
    un nouveau numéro de commande en incrémentant de 1 le dernier numéro ajouté et en concaténant le numéro obtenu avec la chaîne 'COM'.
    Ca c'est extremement dangereux, si 2 personne valide une commande en meme temps, tu te retrouvera avec 2 commandes portant le meme numéro.

    concernant ton probleme d'increment auto, personnellement une fois que j'ai inséré la ligne de commande, je fais un select sur la table avec des critères CLAIREMENT discriminant pour trouver l'ID.

    Par exemple, dans une de mes applications, j'enregistre l'utilisateur et la station de saisie, je fait donc une requete pour trouver le dernier enregistrement fait pour cet utilisateur et cette station, il est impossible que le meme opérateur sur la meme station valide 2 commandes en moins de 1 minute.

    Il existe plusieurs méthodes plus ou moins correctes :
    http://nepomiachty.developpez.com/index_access/

  6. #6
    Membre expérimenté
    Avatar de zekey
    Profil pro
    Inscrit en
    Février 2005
    Messages
    1 036
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 1 036
    Points : 1 403
    Points
    1 403
    Par défaut
    Salut,

    sous postgres tu peux faire nextval('foo_bar_seq')
    et le mettre dans une variable pour le reutiliser apres.

    Pour la table:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    create sequence foo_bar_seq;
    create table foo (bar integer unique not null
    default nextval('foo_bar_seq'));

    --------------------------------------------------------------------
    Steve Hostettler
    ze_key@hotmail.com / www.zekey.net

  7. #7
    Membre régulier
    Inscrit en
    Juillet 2004
    Messages
    306
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 306
    Points : 122
    Points
    122
    Par défaut
    Ca c'est extremement dangereux, si 2 personne valide une commande en meme temps, tu te retrouvera avec 2 commandes portant le meme numéro.
    Ah ouais, c juste.
    J'ai suivi le tutoriel de SQLPro. Clefs auto incrémentées.
    http://sql.developpez.com/clefs/
    Je vais aller le relire, des fois que j'aurais loupé quelque chose.

    Mais si je mets l'insertion d'une nouvelle commande dans une transaction, ça ne pourrait pas aller ?

    Je vais aller voir le lien que tu m'as filé,
    merci
    ++

  8. #8
    Expert confirmé

    Profil pro
    Inscrit en
    Avril 2002
    Messages
    3 338
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Avril 2002
    Messages : 3 338
    Points : 4 657
    Points
    4 657
    Par défaut
    Citation Envoyé par etiennegaloup
    Ah ouais, c juste.
    J'ai suivi le tutoriel de SQLPro. Clefs auto incrémentées.
    http://sql.developpez.com/clefs/
    Je vais aller le relire, des fois que j'aurais loupé quelque chose.
    Ca c'est sur car SQLPro désapprouve completement cette manière de faire.


    Citation Envoyé par etiennegaloup
    Mais si je mets l'insertion d'une nouvelle commande dans une transaction, ça ne pourrait pas aller ?
    La ca dépend de la perméabilité de la transaction, dans le cas d'une transaction nonperméable, le probleme sera encore plus violent.

  9. #9
    Membre régulier
    Inscrit en
    Juillet 2004
    Messages
    306
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 306
    Points : 122
    Points
    122
    Par défaut
    un nouveau numéro de commande en incrémentant de 1 le dernier numéro ajouté et en concaténant le numéro obtenu avec la chaîne 'COM'.
    Quand je disais ça, je n'ai pas précisé, mais le numéro incrémenté de 1 figure dans une table clef. Ainsi, si une nouvelle valeur est ajouté, le numéro est automatiquement incrémenté, et modifié dans la table clef. Le numéro obtenu est concaténé à la chaîne de caractère 'COM'. J'obtiens alors le numéro de commande, et je l'ajoute à ma table commande.
    C mieux comme ça ?

    Parce que effectivement, si je prends la valeur max des clefs de la table commande, là je reconnaît que ça craint. Mais en utilisant, une table clef, ça pose moins de problème, n'est-ce pas ?

    En conclusion,
    je peux réaliser une fonction d'insertion de nouvelles commandes.
    Cette fonction me retourne le numéro de commande auto-généré avec la méthode décrite ci-dessus.
    Avec ce numéro de commande, je peux éditer la table relationnelle en insérant les articles rattachés à la commande.
    Qu'en pensez-vous ?

    ++

  10. #10
    Expert confirmé

    Profil pro
    Inscrit en
    Avril 2002
    Messages
    3 338
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Avril 2002
    Messages : 3 338
    Points : 4 657
    Points
    4 657
    Par défaut
    Citation Envoyé par etiennegaloup
    Quand je disais ça, je n'ai pas précisé, mais le numéro incrémenté de 1 figure dans une table clef. Ainsi, si une nouvelle valeur est ajouté, le numéro est automatiquement incrémenté, et modifié dans la table clef. Le numéro obtenu est concaténé à la chaîne de caractère 'COM'. J'obtiens alors le numéro de commande, et je l'ajoute à ma table commande.
    C mieux comme ça ?
    Toujours pas. Le probleme est le meme, rien n'empeche que 2 select soit fait.

    Exemple :
    Max(Cle) = 48

    Si 2 personne lance la meme action :
    Temps 1 : Process 1 -> Lecture Clé
    Temps 2 : Process 2 -> Lecture Clé
    Temps 3 : Process 1 -> Mise à jour Clé = Clé +1
    Temps 4 : Process 2 -> Mise à jour Clé = Clé +1


    Process 1 et 2 on la meme clé 49 et en plus la clé 50 n'est pas utilisé.

    Toute opération du type select max(champ) from table, quelque soit la table n'est pas une bonne solution.

  11. #11
    Expert confirmé

    Profil pro
    Inscrit en
    Avril 2002
    Messages
    3 338
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Avril 2002
    Messages : 3 338
    Points : 4 657
    Points
    4 657
    Par défaut
    Olivier propose une solution pas mal, c'est de generer un numéro aléatoire que tu met dans un champs quelconque lors de ton INSERT.

    Tu fais un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Select id where monchamp=monnombrealeatoire
    La probabilité que 2 personnes fasse un insert en meme temps avec le meme nombre aléatoire généré est quasiment impossible.

    Une fois que tu as récupéré ton ID, tu vide le champs qui contient la valeur aléatoire.

    Maintenant tu es sur que l'ID que tu as est bien le tiens et pas celui du voisin.

  12. #12
    Membre régulier
    Inscrit en
    Juillet 2004
    Messages
    306
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 306
    Points : 122
    Points
    122
    Par défaut

    Je reconnais que je n'ai pas été du tout très clair.

    En fait, je n'utilise pas select(max).

    Comme il est conseillé dans l'article de SQLPro, j'utilise un trigger et une fonction.

    Voici le trigger:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    CREATE TRIGGER trgInsCommande
        BEFORE INSERT ON fournisseur
        FOR EACH ROW
        EXECUTE PROCEDURE insCommande();
    et voici la fonction:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    CREATE FUNCTION insCommande() RETURNS "trigger"
        AS '
    begin
    new.commandeId=((''COM'')||((select clef from cle where nomtable like ''commande'')+1));
    update cle set clef=clef+1 where nomtable like ''commande'';
    return new;
    end;
    '
        LANGUAGE plpgsql;
    Et voili, voilou.

    Alors cette fois-ci, ça va ? C mieux, non ?
    Et donc, je n'ai plus qu'à rajouter dans cette fonction un renvoi de la clef insérée. Ainsi mon formulaire php, récupérera cette clef, et l'utilisera pour ajouter dans la table relationnelle, les articles rattachés à la commande.

    Qu'en pensez-vous ?
    ++

  13. #13
    Membre régulier
    Inscrit en
    Juillet 2004
    Messages
    306
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 306
    Points : 122
    Points
    122
    Par défaut
    Olivier propose une solution pas mal, c'est de generer un numéro aléatoire que tu met dans un champs quelconque lors de ton INSERT.
    Ouais c plutôt bien ça.

    Et ma proposition précédente ?

  14. #14
    Membre expérimenté
    Avatar de zekey
    Profil pro
    Inscrit en
    Février 2005
    Messages
    1 036
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 1 036
    Points : 1 403
    Points
    1 403
    Par défaut
    En quoi la solution de la sequence et du nextval, ne résout pas ton probleme de facon propre ?


    --------------------------------------------------------------------
    Steve Hostettler
    ze_key@hotmail.com / www.zekey.net

  15. #15
    Membre régulier
    Inscrit en
    Juillet 2004
    Messages
    306
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 306
    Points : 122
    Points
    122
    Par défaut
    Si cette solution est super aussi,
    je vais la tester.
    ++

  16. #16
    Expert confirmé

    Profil pro
    Inscrit en
    Avril 2002
    Messages
    3 338
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Avril 2002
    Messages : 3 338
    Points : 4 657
    Points
    4 657
    Par défaut
    Pour moi, le fait de faire un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    SELECT clé+1
    UPDATE clé=clé+1
    Pose toujours le meme probleme, si quelqu'un lance également un insert avant que l'autre soit fini, tu te retrouve de nouveau avec un truc bizarre.

    Exemple :
    Temps 1 : (Proc 1) Insert dans la table Commande (clé 49 en auto-incrément)
    Temps 2 : (Proc 1) Trigger déclenché, lecture clé : 48
    Temps 3 : (Proc 2) Insert dans la table Commande (clé 50 en auto-increment)
    Temps 4 : (Proc 2) Trigger déclenché, lecture clé : 48
    Temps 5 : (Proc 1) update clé : 48+1
    Temps 6 : (Proc 1) update clé : 48+1

    Moralité ta proc te renvoi 49 les 2 fois, alors que c'est vrai juste dans 1 des 2 cas.

    Effectivement le principe d'un SELECT suivi immediatement d'un UPDATE par trigger limite la probabilité, mais elle n'est pas nulle.

    C'est une solution satisfaisante.

  17. #17
    Membre émérite
    Avatar de hpalpha
    Inscrit en
    Mars 2002
    Messages
    769
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 769
    Points : 2 545
    Points
    2 545
    Par défaut
    Bonjour,

    je n'avais pas vu ce post, mais tu aurais du le mettre sur le forum PostgreSQL directement.
    Pour ton probleme de clef autoinc, pg dispose de sequence, c'est un moyen sur et efficace, tu trouvera un tuto dessus ici :
    http://dgriessinger.developpez.com/p...sql/sequences/

  18. #18
    Membre régulier
    Inscrit en
    Juillet 2004
    Messages
    306
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 306
    Points : 122
    Points
    122
    Par défaut
    Pour moi, le fait de faire un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    SELECT clé+1
    UPDATE clé=clé+1
    Pose toujours le meme probleme, si quelqu'un lance également un insert avant que l'autre soit fini, tu te retrouve de nouveau avec un truc bizarre.
    Ok, je vois (enfin) ce que tu veux dire. Il est vrai qu'il y a un risque qui n'est pas insignifiant. Merci en tout cas, pour tes réponses, et ta patience.

    Citation Envoyé par ze_key
    Salut,

    sous postgres tu peux faire nextval('foo_bar_seq')
    et le mettre dans une variable pour le reutiliser apres.
    Suite à ta réponse et à la réponse de hpalpha, j'ai lu le tuto sur les séquences et je pense effectivement, que je vais me tourner vers les séquences.

    Merci à tous pour vos nombreuses réponses.

    ++

  19. #19
    Membre expert
    Avatar de TheLeadingEdge
    Inscrit en
    Mai 2005
    Messages
    1 199
    Détails du profil
    Informations forums :
    Inscription : Mai 2005
    Messages : 1 199
    Points : 3 103
    Points
    3 103
    Par défaut
    Ca c'est extremement dangereux, si 2 personne valide une commande en meme temps, tu te retrouvera avec 2 commandes portant le meme numéro.
    Pose toujours le meme probleme, si quelqu'un lance également un insert avant que l'autre soit fini, tu te retrouve de nouveau avec un truc bizarre.
    C bien pour ça que j'avais conseillé de faire ttes les maj ds 1 transaction. Tant que tu n'a pas fait 'commit' ou 'rollback' personne ne peux modifier quoi que ce soit ds les tables.

  20. #20
    Expert confirmé

    Profil pro
    Inscrit en
    Avril 2002
    Messages
    3 338
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Avril 2002
    Messages : 3 338
    Points : 4 657
    Points
    4 657
    Par défaut
    Citation Envoyé par TheLeadingEdge
    Tant que tu n'a pas fait 'commit' ou 'rollback' personne ne peux modifier quoi que ce soit ds les tables.
    J'aimerai bien voir ça ??????
    Le principe de la transaction permet de garder l'unicité d'un traitement en aucun cas de gérer des problèmes de concurrence d'accès à l'insertion (enfin pas dans ce cas là).

    Hors mode propre à Postgres ou mode transactionnelle particulier, les 95% de transaction utilisé sont dites non perméable, c'est à dire que les opérations effectué avant le COMMIT ne sont pas validé dans la base et donc pas disponible pour un SELECT hors transaction.

    Par exemple, si tu insère dans une table Commande une ligne de commande, puis dans une table commande_article la liste des articles commandés, il faut une transaction car la commande et son détail est une opération atomique au sens fonctionnel.

    Il ne faut pas que quelqu'un puisse voir la commande avant que le détail ne soit enregistré dans la base, d'ou le principe de transaction.

    Justement dans notre cas il faut au contraire ABSOLUMENT que les autres curseur soient averti de l'utilisation d'un numero de clé.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. [ZEOSLIB] Problème Insertion dans une table
    Par moscovisci dans le forum Bases de données
    Réponses: 1
    Dernier message: 09/06/2005, 12h05
  2. [interbase6]probleme d'insertion dans une table
    Par macadam314 dans le forum Bases de données
    Réponses: 10
    Dernier message: 22/02/2005, 14h21
  3. [Sybase] Temps d'une insertion dans une table
    Par vsavoir dans le forum Décisions SGBD
    Réponses: 5
    Dernier message: 14/02/2005, 10h04
  4. Extraction d'un .txt et Insertion dans une table
    Par PoPmiSiR dans le forum Access
    Réponses: 8
    Dernier message: 28/10/2004, 19h13
  5. Détection insertion dans une Table
    Par abelman dans le forum MS SQL Server
    Réponses: 5
    Dernier message: 06/07/2004, 14h24

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo