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

SQL Procédural MySQL Discussion :

Clonage Table Mere et ses Fils ainsi que les petits fils (1-n, 1-m)


Sujet :

SQL Procédural MySQL

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    279
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 279
    Par défaut Clonage Table Mere et ses Fils ainsi que les petits fils (1-n, 1-m)
    Bonjour,

    J'ai ce schema :
    - Table 'Entity' (entity_id, completed, reference_year)
    - Table 'Transaction' (transaction_id, statut, entity_id)
    - Table 'Document'(document_id, transaction_id, fichier)

    Les relations entre elles sont les suivantes :
    - 1 Entity peut avoir plusieurs transactions (1-n)
    - 1 Transaction peut avoir plusieurs documents (1-m)

    Je souhaite cloner les transactions d'une entité (sous conditions) ainsi que leurs documents en utilisant un trigger.

    Pour cela, j'ai fait ces deux triggers, le premier permet de cloner les transactions et le second permet de cloner les document ou fur et a mesure qu'une transaction est cloner.

    Voici le code sql utilisée :

    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
     
     
    -- Trigger clone Transaction
    CREATE TRIGGER `test_transaction` AFTER
    INSERT ON `entity`
    FOR EACH
            ROW BEGIN                 
     
            set @newValue = new.ENTITY_ID;
     
               INSERT INTO transaction(STATUS, ENTITY_ID)
     
               SELECT 'DRAFT', @newValue
     
               FROM entity a, transaction c
     
               WHERE a.entity_id = c.entity_id AND
                         c.status IN ('VALIDATED', 'IN_PROGRESS') AND a.completed =      
                         1 AND year(a.reference_year) = year(new.reference_year)-1 
                         group by c.transaction_id;                                                                                  
     
    END;
     
    commit;
     
    -- Trigger clone documents
     
    CREATE TRIGGER `clone_document` AFTER
    INSERT ON `transaction`
    FOR EACH
            ROW BEGIN     
     
            if new.parent_id is not null then  -- parent_id est dans la table transaction   
     
                set @newValue = new.transaction_id;       
     
                  INSERT INTO document(TRANSACTION_ID, FICHIER)
                  SELECT @newValue, c.FICHIER
                  FROM transaction a, document c
                  WHERE a.transaction_id = c.transaction_id                        
                  group by c.document_id;   
     
            end if;                
     
    END;
     
    commit;
    Quand je fait un insert dans entity , j'ai cette erreur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Cannot add or update a child row: a foreign key constraint fails (`optidoc`.`transaction`, CONSTRAINT `FK_TRANSACTION_ENTITY` FOREIGN KEY (`ENTITY_ID`) REFERENCES `entity` (`ENTITY_ID`))
    Par contre si je supprime le second trigger et je clone uniquement les transactions, le clonage fonctionne bien.

    Si vous pouvez m'aider a resoudre ce probleme de clonage de deux niveaux.

    Merci

  2. #2
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    22 021
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 22 021
    Billets dans le blog
    6
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  3. #3
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    279
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 279
    Par défaut
    J'ai renommé la table 'transaction' on 'les_transaction', l'erreur existe toujours :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Cannot add or update a child row: a foreign key constraint fails (`optidoc`.`les_transaction`, CONSTRAINT `FK_TRANSACTION_ENTITY` FOREIGN KEY (`ENTITY_ID`) REFERENCES `entity` (`ENTITY_ID`))

    Citation Envoyé par SQLpro Voir le message

  4. #4
    Expert éminent
    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 818
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 818
    Billets dans le blog
    14
    Par défaut
    "les_transaction" n'est guère mieux comme nom de table !
    Il manquerait un s à transaction et en principe on ne nomme pas les tables au pluriel.

    Tu peux adapter le standard de nommage de SQLPro qui n'entraînera jamais d'erreur (ni de remarques désobligeantes de sa part ! ).
    Ça pourrait donner dans ton cas, avec mon standard de nommage inspiré de celui de SQLPro :
    te_entity_ent (ent_id, ent_completed, ent_referenced_year)
    te_transaction_trs (trs_id, trs_id_entity, trs_statut)
    te_document_doc (doc_id, doc_id_transaction, doc_fichier)

    Le problème ne serait-il pas ici :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SET @newValue = new.ENTITY_ID;
    Ne faudrait-il pas plutôt utiliser LAST_INSERT_ID
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole, en retraite... mais toujours Autoentrepreneur à l'occasion.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  5. #5
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    279
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 279
    Par défaut
    J'ai changer le NEW.identity_id en last_index_id(), j'ai la meme erreur

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Cannot add or update a child row: a foreign key constraint fails (`optidoc`.`les_transactions`, CONSTRAINT `FK_TRANSACTION_ENTITY` FOREIGN KEY (`ENTITY_ID`) REFERENCES `entity` (`ENTITY_ID`))

    Citation Envoyé par CinePhil Voir le message
    "les_transaction" n'est guère mieux comme nom de table !
    Il manquerait un s à transaction et en principe on ne nomme pas les tables au pluriel.

    Tu peux adapter le standard de nommage de SQLPro qui n'entraînera jamais d'erreur (ni de remarques désobligeantes de sa part ! ).
    Ça pourrait donner dans ton cas, avec mon standard de nommage inspiré de celui de SQLPro :
    te_entity_ent (ent_id, ent_completed, ent_referenced_year)
    te_transaction_trs (trs_id, trs_id_entity, trs_statut)
    te_document_doc (doc_id, doc_id_transaction, doc_fichier)

    Le problème ne serait-il pas ici :


    Ne faudrait-il pas plutôt utiliser LAST_INSERT_ID

  6. #6
    Expert éminent
    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 818
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 818
    Billets dans le blog
    14
    Par défaut
    Citation Envoyé par facilus68 Voir le message
    J'ai changer le NEW.identity_id en last_index_id()
    Ce n'est pas last_index_id mais LAST_INSERT_ID !

    L'erreur indique que la valeur passée à la colonne entity_id n'a pas de correspondance dans la colonne de référence entity.entity_id.

    Mon diagnostic est que @newValue n'est pas correctement valorisé.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole, en retraite... mais toujours Autoentrepreneur à l'occasion.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  7. #7
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    279
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 279
    Par défaut
    Pardon, j'ai mis effectivement last_insert_id() et pareil l'erreur existe.

    Pour ma part, mon diagnostic est le suivant :
    - Quand il y'a un insert dans transaction, le trigger pour les documents se déclenche

    ma question est es ce que sans le COMMIT, le nouveau id de la transaction inserer existe ?

    Citation Envoyé par CinePhil Voir le message
    Ce n'est pas last_index_id mais LAST_INSERT_ID !

    L'erreur indique que la valeur passée à la colonne entity_id n'a pas de correspondance dans la colonne de référence entity.entity_id.

    Mon diagnostic est que @newValue n'est pas correctement valorisé.

  8. #8
    Expert éminent
    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 818
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 818
    Billets dans le blog
    14
    Par défaut
    entity_id est bien en auto-incrément dans la table entity au moins ?
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole, en retraite... mais toujours Autoentrepreneur à l'occasion.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  9. #9
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    279
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 279
    Par défaut
    Oui

    Citation Envoyé par CinePhil Voir le message
    entity_id est bien en auto-incrément dans la table entity au moins ?

  10. #10
    Expert éminent
    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 818
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 818
    Billets dans le blog
    14
    Par défaut
    Je n'avais pas regardé le code de ton trigger en détail :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
              INSERT INTO transaction(STATUS, ENTITY_ID)
     
               SELECT 'DRAFT', @newValue
     
               FROM entity a, transaction c
     
               WHERE a.entity_id = c.entity_id AND
                         c.STATUS IN ('VALIDATED', 'IN_PROGRESS') AND a.completed =      
                         1 AND year(a.reference_year) = year(new.reference_year)-1 
                         GROUP BY c.transaction_id;
    À quoi sert la partie FROM et la jointure (écrite avec la syntaxe obsolète depuis 20 ans ! ) ?

    En plus, un GROUP BY sans fonction de groupage, ça ne sert à rien ou c'est un mauvais choix de fonction !

    As-tu testé la requête hors trigger ?
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole, en retraite... mais toujours Autoentrepreneur à l'occasion.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  11. #11
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    279
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 279
    Par défaut
    J'ai fais une jointure classique dans le from et where

    J'ai tester la requete toute seul, ca fonctionne trés bien, d'ailleurs si je supprime le second trigger, le clonage des transactions fonctionne correctement avec le premier trigger.

    Citation Envoyé par CinePhil Voir le message
    Je n'avais pas regardé le code de ton trigger en détail :

    À quoi sert la partie FROM et la jointure (écrite avec la syntaxe obsolète depuis 20 ans ! ) ?

    En plus, un GROUP BY sans fonction de groupage, ça ne sert à rien ou c'est un mauvais choix de fonction !

    As-tu testé la requête hors trigger ?

  12. #12
    Membre émérite
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    445
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2011
    Messages : 445
    Par défaut
    Citation Envoyé par CinePhil Voir le message
    Je n'avais pas regardé le code de ton trigger en détail :

    À quoi sert la partie FROM et la jointure (écrite avec la syntaxe obsolète depuis 20 ans ! ) ?

    En plus, un GROUP BY sans fonction de groupage, ça ne sert à rien ou c'est un mauvais choix de fonction !

    As-tu testé la requête hors trigger ?
    Effectivement ton code n'est pas très clair.

    Soit tu veux toujours insérer une ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    INSERT INTO transaction(STATUS, ENTITY_ID) VALUES ('DRAFT', new.ENTITY_ID);
    Soit l'insérer dans certains cas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     SELECT DISTINCT 'DRAFT', new.ENTITY_ID FROM ...  WHERE ...

  13. #13
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    279
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 279
    Par défaut
    En fesant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    SELECT DISTINCT 'DRAFT', new.ENTITY_ID FROM ...  WHERE ...
    Je regroupe tous en une seul en raison que new_Entity_id est unique, j'aurais qu'une ligne a cloner, par contre en fesant un group by sur la transaction_id et en utilisant les where ca fonctionne trés bien le clonage

    Mon souci est le clonage du second niveau. C'est a dire quand j'active le second trigger des documents, l'erreur des cles apparait.

    Y'a t'il une autre solution d'ecrire les triggers en respectant cette spec. (PS : schema base au debut du post) :

    - Quand je crée une 'ENTITY', je verifie si cette derniere existe à l'année précedente, si c'est le cas, je clone toute les transactions de l'entité (n-1) vers l'année (n).

    - Je clone aussi tous les documents liées au transactions de l'entité (n-1)

    Exemple :

    - E1 crée à l'année n , E1 existe à l'année (n-1) et contient (T1, T2) comme transactions à l'année (n-1)
    - T1 contient D1, D2 comme document à l'année (n-1)
    - T2 contient D3 comme document à l'année (n-1)

    Resultat attendu à l'année (n) :

    - E1 crée à l'année (n) et contient (T1_Cloné, T2_Cloné) comme transactions à l'année (n)
    - T1_Cloné contient D1_Cloné, D2_Cloné comme document à l'année (n)
    - T2_Cloné contient D3_Cloné à l'année (n)

    Je suis bloqué au second niveau du clonage

    Merci pour votre aide

    Citation Envoyé par Fred_34 Voir le message
    Effectivement ton code n'est pas très clair.

    Soit tu veux toujours insérer une ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    INSERT INTO transaction(STATUS, ENTITY_ID) VALUES ('DRAFT', new.ENTITY_ID);
    Soit l'insérer dans certains cas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     SELECT DISTINCT 'DRAFT', new.ENTITY_ID FROM ...  WHERE ...

  14. #14
    Expert éminent
    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 818
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 818
    Billets dans le blog
    14
    Par défaut
    Tu dis que tu es bloqué au second niveau du clonage, pourtant ton message d'erreur concerne bien le premier niveau, c'est à dire que c'est l'insertion dans la table des transactions qui pose problème car la référence de l'identifiant de l'entité n'est pas trouvée dans la table entity.
    Cannot ADD OR UPDATE a child row: a FOREIGN KEY constraint fails (`optidoc`.`transaction`, CONSTRAINT `FK_TRANSACTION_ENTITY` FOREIGN KEY (`ENTITY_ID`) REFERENCES `entity` (`ENTITY_ID`))
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole, en retraite... mais toujours Autoentrepreneur à l'occasion.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  15. #15
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    279
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 279
    Par défaut
    Oui, mais si j'enleve le Trigger du second niveau :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    DROP TRIGGER IF EXISTS `clone_document` ;
    Et je fait un insert dans 'Entity' , le clonage fonctionne tres bien.

    J'ai fais un autre test, qui est le suivant :

    - J'ai garder le second Trigger et j'ai inserer une ENTITY ayant UNIQUEMENT UNE SEULE transaction, pour ce cas, le clonage de la transaction a bien eu lieu mais pas les documents.

    J'ai compris que lorsqu'il y'a plusieurs transactions, le clonage se fait uniquement pour la premiere transaction sans ces documents et apres le passage vers les autres transactions , y'a le bug.

    J'esseye d'affciher les traces lors du clonage mais la methode 'print' ou 'select' ne fonctionne pas dans le trigger.

    Citation Envoyé par CinePhil Voir le message
    Tu dis que tu es bloqué au second niveau du clonage, pourtant ton message d'erreur concerne bien le premier niveau, c'est à dire que c'est l'insertion dans la table des transactions qui pose problème car la référence de l'identifiant de l'entité n'est pas trouvée dans la table entity.

  16. #16
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    279
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 279
    Par défaut
    J'ai rajouté une modification qui ma permet de n'avoir plus l'erreur , et comme suit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    set @newEntityId = '';
    select entity_id into @newEntityId from les_transaction where transaction_id = @newValue;
     
    WHERE a.parent_id = c.transaction_id AND a.entity_id = @newEntityId
    Apres insertion, la premiere transaction est bien cloné ainsi que document joint, mais la suite des transactions ne sont pas cloné

Discussions similaires

  1. Réponses: 2
    Dernier message: 18/01/2011, 06h44
  2. Réponses: 2
    Dernier message: 18/01/2011, 06h44
  3. Réponses: 1
    Dernier message: 22/04/2010, 17h41
  4. Réponses: 2
    Dernier message: 05/02/2008, 18h53
  5. Réponses: 2
    Dernier message: 30/06/2006, 16h12

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