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. #21
    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,

    Comme je ne suis plus sur de rien, je récapitule ce que j'ai compris du pb :
    Créer 1 cde avec 1 n° auto
    Créer les lignes de cette cde
    2 contraintes :
    il faut renseigner le N° de cde ds las lignes.
    il ne faut pas mélanger les lignes de plusieurs cdes.

    J'ai essayé ça ce matin :

    Création schéma
    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
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    DROP SEQUENCE seqprod;
    DROP SEQUENCE seqcmde;
    CREATE SEQUENCE seqprod;
    CREATE SEQUENCE seqcmde;
     
    DROP TABLE r_prod_cmd;
    DROP TABLE t_commande;
    DROP TABLE t_produit;
    CREATE TABLE t_produit 
    ( 
       	prod_Id INTEGER NOT NULL DEFAULT NEXTVAL ('seqprod'),
       	prod_Libelle VARCHAR(32) NOT NULL,
    	PRIMARY KEY (prod_Id)
    ) TABLESPACE "DVP";
     
    CREATE TABLE t_commande 
    ( 
       	cmd_Id INTEGER NOT NULL DEFAULT NEXTVAL ('seqcmde'),
       	cmd_Date TIMESTAMP NOT NULL,
    	PRIMARY KEY (cmd_Id)
    ) TABLESPACE "DVP";
     
    CREATE TABLE r_prod_cmd 
    ( 
       	cmd_Id INTEGER NOT NULL,
       	prod_Id INTEGER NOT NULL,
       	qte INTEGER NOT NULL,
    	PRIMARY KEY (cmd_Id, prod_Id),
    	FOREIGN KEY (cmd_Id) REFERENCES t_commande (cmd_Id),
    	FOREIGN KEY (prod_Id) REFERENCES t_produit (prod_Id)	
    ) TABLESPACE "DVP";
     
    INSERT INTO t_produit (prod_Libelle)
    (
    SELECT 'Produit 1' 
    UNION ALL
    SELECT 'Produit 2'
    UNION ALL
    SELECT 'Produit 3'
    UNION ALL
    SELECT 'Produit 4'
    );
    Insertion d'1 cde et de ces lignes :
    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
    BEGIN TRANSACTION;
     
    INSERT INTO t_commande (cmd_Date)
    (
    SELECT current_date
    );
     
    INSERT INTO r_prod_cmd (cmd_Id, prod_Id, qte) 
    (
    SELECT MAX(cmd_Id), 1, 10 FROM t_commande
    );
    INSERT INTO r_prod_cmd (cmd_Id, prod_Id, qte) 
    (
    SELECT MAX(cmd_Id), 3, 30 FROM t_commande
    );
    J'ai volontairement omis le COMMIT, et j'ai lancé plusieurs autres insertions dans des fenêtres SQL différentes. Elles sont ttes restées bloquées par le 'LOCK' tant que je n'ai pas committé la première par COMMIT WORK;
    C'est ce que je voulais obtenir :
    -La création d'une cde avec 1 id autoincrementé
    -les lignes de cdes contiennent bien l'id de la cde.
    -tant que cette cde la n'est pas validée, on ne peut pas en insérer 1 autre, donc pas de risque de mélange.

    @Gaël Donat: Est-ce que j'ai 1 risque en faisant comme ça ? J'ai tjours cru que c'était bon, mais comme ça ne semble pas aussi simple, merci de me corriger.

    NB : J'ai fait la même chose avec SQL Server avec le même résultat.

    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
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    USE DVP;
     
    DROP TABLE r_prod_cmd;
    DROP TABLE t_commande;
    DROP TABLE t_produit;
    CREATE TABLE t_produit 
    ( 
       	prod_Id INTEGER NOT NULL IDENTITY (1,1), 
       	prod_Libelle VARCHAR(32) NOT NULL,
    	PRIMARY KEY (prod_Id)
    ); 
     
    CREATE TABLE t_commande 
    ( 
       	cmd_Id INTEGER NOT NULL IDENTITY (1,1),
       	cmd_Date DATETIME NOT NULL,
    	PRIMARY KEY (cmd_Id)
    ); 
     
    CREATE TABLE r_prod_cmd 
    ( 
       	cmd_Id INTEGER NOT NULL,
       	prod_Id INTEGER NOT NULL,
       	qte INTEGER NOT NULL,
    	PRIMARY KEY (cmd_Id, prod_Id),
    	FOREIGN KEY (cmd_Id) REFERENCES t_commande (cmd_Id),
    	FOREIGN KEY (prod_Id) REFERENCES t_produit (prod_Id)	
    );
     
    INSERT INTO t_produit (prod_Libelle) 
    (
    SELECT 'Produit 1'
    UNION ALL
    SELECT 'Produit 2'
    UNION ALL
    SELECT 'Produit 3'
    );
     
    --SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
    BEGIN TRANSACTION;
     
    INSERT INTO t_commande (cmd_Date)
    (
    SELECT getdate()
    );
     
    INSERT INTO r_prod_cmd (cmd_Id, prod_Id, qte) 
    (
    SELECT MAX(cmd_Id), 1, 10 FROM t_commande
    );
    INSERT INTO r_prod_cmd (cmd_Id, prod_Id, qte) 
    (
    SELECT MAX(cmd_Id), 3, 30 FROM t_commande
    );
     
    COMMIT WORK;
    --SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

  2. #22
    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
    @Gaël Donat: Est-ce que j'ai 1 risque en faisant comme ça ? J'ai tjours cru que c'était bon, mais comme ça ne semble pas aussi simple, merci de me corriger.
    Non c'est correct au sens fonctionnel, le lock empeche evidemment que 2 personnes se voient assigné le meme identifiant de commande, ce qui est ce qu'on veut, donc pour répondre au probleme c'est correct.

    Maintenant imaginons que l'outil de commande soit utilisé par 800 personnes chargés de prendre des commandes, si chaque vendeur attend son tour pour que la base donne un numéro de commande, le dernier arrivé risque d'attendre fort longtemps, c'est ce qu'on nomme la contention.

    Mon premier exemple avec un select sur des critères discriminants permet de ne pas avoir des soucis de cet ordre là, prenons un exemple concret :

    Imaginons 25 opérateurs (avec un login pour chacun du type "OP1", "OP2"..."OP25") qui valide ensemble la saisie de 25 commandes, le moteur de base de données va ajouter 25 numéro de commande en meme temps dans la base de données.

    Comme c'est le SGBD qui s'occupe d'attribuer des numéros, nous n'avons pas de soucis de clé primaire doublonnés, c'est impossible car c'est un auto-incrément.

    Notre problème réside dans le fait de trouver quel numéro de commande est attribué par le SGBD pour chaque opérateurs car l'application à besoin de savoir quel est le numéro attribué pour inserer ensuite le détail des commandes dans la table détail-commande avec comme clé étrangère le fameux numéro de commande.

    Si on fait un SELECT Max(num_commande) from commandes; la requete va invariablement nous renvoyer le meme numéro de commande pour les 25 opérateurs, ce qui à l'evidence n'est pas correcte.

    Une solution consiste donc à trouver une autre information discriminante, dans mon cas j'utilise le login de l'opérateur.

    J'insere pour chaque commande le login ("OPxx") de l'opérateur qui a saisie la commande.

    Pour trouver le numéro de la commande que l'opérateur à saisie j'ai juste à faire :
    SELECT Max(num_commande) from commandes where oper="OP1";

    Ma requete me donne la dernière commande saisie par l'opérateur OP1, c'est exactement ce que je veux savoir.

    Et le résultat est evidemment différent si je met OP2 ou OP3

    En faisant ça de 1 à 25, je retrouve bien mes 25 ID de commande pour chaque opérateur.

    Je peux donc continuer mon insertion sans risque de chevauchement.

    Je ne sais pas si je suis clair.

  3. #23
    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
    re,

    Ouf...Tu me rassures ! J'avoue que ton précédent post m'avait 1 peu inquiété !

    Citation Envoyé par Gaël Donat
    Je ne sais pas si je suis clair.
    Limpide !

    Pour les cas ou 'locker' la table par 1 tx est inapproprié (trop de tables, ou trop long, ...) , j'utilise 1 'lock' logique, 1 timestamp ds le dernier tuple inséré ds la table, qui est non nul tant qu'une 'transaction' est en cours, ce qui indique aux autres qu'il faut attendre. Mais pour que ça marche, il faut que tt le monde fasse la même chose (ce qui n'est pas gagné tant qu'on aura pas encapsulé les ordres SQL ds des objects spécialisés, mais là je disgresse).
    Ta solution est nettement plus souple. Je l'ai dèjà rangée ta ds ma 'boite à trucs utiles'.

    Merci pour ta réponse,

    A +

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 2 PremièrePremière 12

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