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

Développement SQL Server Discussion :

Le code du trigger fonctionne en testant via une requête mais ne fait pas son job en tant que trigger


Sujet :

Développement SQL Server

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre expérimenté
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Par défaut Le code du trigger fonctionne en testant via une requête mais ne fait pas son job en tant que trigger
    Hello,

    Le titre n'est p-e pas très clair alors voici quelques explications.

    Toujours au sujet des promotions (à propos desquelles je vous sollicite depuis quelques temps), j'ai rédigé le trigger suivant :
    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
     
    CREATE TRIGGER [S_PROMO].[TRG_AFTER_INSERT_PDI] 
    ON [S_PROMO].[T_PRODUCT_DEMO_IN_PDI] 
    AFTER UPDATE AS 
    BEGIN 
        SET NOCOUNT ON;  
     
        WITH T(PDI_BARCODE, PED_ID) AS (
            SELECT    INS.PDI_BARCODE,
                    CASE
                        WHEN PED.PED_PERCENTAGE < PED2.PED_PERCENTAGE THEN PED.PED_ID
                        ELSE PED2.PED_ID
                    END AS 'PED_ID'
            FROM    INSERTED INS
                        INNER JOIN S_PROMO.T_PRODUCT_DEMO_IN_PDI PDI
                            ON    INS.PDI_BARCODE = PDI.PDI_BARCODE
                            AND    INS.PED_ID <> PDI.PED_ID
                            INNER JOIN S_PROMO.T_PERCENTAGE_DEMO_PED PED
                                ON PDI.PED_ID = PED.PED_ID
                        INNER JOIN S_PROMO.T_PERCENTAGE_DEMO_PED PED2
                            ON    INS.PED_ID = PED2.PED_ID
            WHERE    PED.DTD_ID = PED2.DTD_ID)
     
        DELETE    S_PROMO.T_PRODUCT_DEMO_IN_PDI
        FROM    S_PROMO.T_PRODUCT_DEMO_IN_PDI PDI
                    INNER JOIN T
                        ON    PDI.PED_ID = T.PED_ID
                        AND    PDI.PDI_BARCODE = T.PDI_BARCODE
     
    END;
    Au niveau des tables, pour que vous ayez une vision de leurs interactions cela s'organise comme ceci : (les colonnes en gras et soulignées sont les PK et les colonnes en italique sont les FK)

    • T_PROMO_PRM(PRM_ID, PRM_NAME, PRM_START, PRM_END) : table contenant le "header" de la promo. Ces infos vraiment spécifique quoi.
    • T_DETAIL_DEMO_DTD(DTD_ID, PRM_ID, CONT_ID) : table contenant les fournisseurs en démonstration qui participe à la promo (un fournisseur en démonstration est en fait un marchand qui loue un espace dans le magasin pour vendre sa marchandise. CONT_ID est la FK qui fait référence à la table des contrats avec ces fournisseurs)
    • T_PERCENTAGE_DEMO_PED(PED_ID, DTD_ID, PED_PERCENTAGE) : table contenant les pourcentages actifs pour chaque fournisseur démo)
    • T_PRODUCT_DEMO_IN_PDI(PED_ID, PDI_BARCODE) : table contenant les références des articles du fournisseurs démo qui participe à la promo. Si aucun article n'est présent dans cette table, alors la promo s'applique sur tous.


    N.B. : Si certains préfèrent le code DDL de ces tables, suffit de demander. Mais il me semble que c'est plus clair ainsi sans avoir des colonnes supplémentaires non essentielles à la problématique qui viennent surcharger le tableau.
    N.B.2 : Par souci de concision, je désignerai les tables par leur suffixe.

    Maintenant, le pourquoi du trigger.
    Si on ajoute dans PDI un article qui a déjà un autre pourcentage, je dois garder la ligne qui donne le plus grand pourcentage sur l'article en question.

    Histoire de tester le trigger, j'ai rempli la table avec quelques références dans différents pourcentage pour un fournisseur X et j'ai fait ceci :
    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
     
    INSERT INTO S_PROMO.T_PRODUCT_DEMO_IN_PDI(PED_ID, PDI_BARCODE)
    SELECT -2147479467,'3596488250893'
    GO
     
    WITH 
    INSERTED(PED_ID, PDI_BARCODE) AS (
        SELECT -2147479467,'3596488250893'),
     T(PDI_BARCODE, PED_ID) AS (
        SELECT    INS.PDI_BARCODE,
                CASE
                    WHEN PED.PED_PERCENTAGE < PED2.PED_PERCENTAGE THEN PED.PED_ID
                    ELSE PED2.PED_ID
                END AS 'PED_ID'
        FROM    INSERTED INS
                    INNER JOIN S_PROMO.T_PRODUCT_DEMO_IN_PDI PDI
                        ON    INS.PDI_BARCODE = PDI.PDI_BARCODE
                        AND    INS.PED_ID <> PDI.PED_ID
                        INNER JOIN S_PROMO.T_PERCENTAGE_DEMO_PED PED
                            ON PDI.PED_ID = PED.PED_ID
                    INNER JOIN S_PROMO.T_PERCENTAGE_DEMO_PED PED2
                        ON    INS.PED_ID = PED2.PED_ID
        WHERE    PED.DTD_ID = PED2.DTD_ID)
     
        DELETE    S_PROMO.T_PRODUCT_DEMO_IN_PDI
        FROM    S_PROMO.T_PRODUCT_DEMO_IN_PDI PDI
                    INNER JOIN T
                        ON    PDI.PED_ID = T.PED_ID
                        AND    PDI.PDI_BARCODE = T.PDI_BARCODE
    J'insère donc une ligne et je simule ensuite la pseudo table INSERTED disponible dans le trigger via un CTE nommée INSERTED et j'y met une valeur. Si je ne fais pas d'erreur, on est donc dans la même situation que si on était vraiment dans le trigger non ?

    Je crée alors une CTE nommée T qui contient le barcode et le PED_ID du pourcentage le plus faible pour les articles qui sont répertoriés dans plusieurs pourcentages pour un même fournisseur.
    Finalement, je supprime de PDI les lignes qui matchent le contenu de T.

    Et là, j'ai bien une ligne supprimée et il ne reste bien dans ma table qu'une seule fois cet article avec 60% (son autre pourcentage était de 50% donc le taff est bien fait).

    Maintenant, lors de l'insertion de la ligne, pourquoi l'article à 50% n'est-il pas supprimé ? Appramment, le même code repris en dehors du trigger produit le resultat escompté. Du coup, je reste perplexe...

    Des suggestions ?

  2. #2
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Par défaut
    Bonjour,

    C'est peut-être juste une erreur de copier/coller ou une mauvaise compréhension de ma part, mais il me semble que votre trigger est conçu pour se déclencher après une insertion dans la table, or vous avez mis :


  3. #3
    Membre expérimenté
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Par défaut
    Oh putain le con !

    Merci aieeeuuuuu.

    Voilà ce qui arrive quand on travaille en sous effectif en faisant 3 choses à la fois... On passe à côté des choses évidentes.

    C'est forcément là le problème... J'ai écrit le trigger en prenant un trigger after update comme base histoire de pas devoir réécrire la déclaration... J'ai changé le nom et le corps du trigger et j'ai oublié cette partie...

    P.S. : Je pense qu'on peut se tutoyer non ? ^^

  4. #4
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Par défaut
    En effet, ça arrive !

    cependant, d'un point de vue conception, je ferai plutôt une procédure stockée pour gérer l'insertion.
    A défaut, un trigger INSTEAD OF qui ferait un MERGE (cette commande n'a plus aucun secret pour toi maintenant )

    Car du coup, il semble manquer une contrainte d'unicité pour n'avoir qu'un seul pourcentage de réduction pour un produit donné...

  5. #5
    Membre expérimenté
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Par défaut
    Citation Envoyé par aieeeuuuuu Voir le message
    En effet, ça arrive !

    cependant, d'un point de vue conception, je ferai plutôt une procédure stockée pour gérer l'insertion.
    A défaut, un trigger INSTEAD OF qui ferait un MERGE (cette commande n'a plus aucun secret pour toi maintenant )

    Car du coup, il semble manquer une contrainte d'unicité pour n'avoir qu'un seul pourcentage de réduction pour un produit donné...
    Je ferai aussi une procédure stockée mais là, je débogue le code d'un collègue qui est partie en congé dans un projet dont l'output est déjà en production et dont il faut corriger les erreurs asap.

    Je pare donc au plus urgent et je reverrai la conception par après.

    Quand à l'unicité d'un seul pourcentage pour un produit donné, j'avais mis la contrainte mais j'ai été forcé de la retirer. Il se trouve que, entre les fournisseurs démo, leurs barcodes ne sont pas uniques...

    Du coup, c'est un peu la pagaille. Heureusement que, à la caisse, pour un produit en démonstration, la caissière doit :
    1. Scanner un premier barcode au format ean13 structuré comme suit : 19CCCCPPPPPPK où CCCC est le code démo (il est unique lui), PPPPPP est le prix de l'article en centimes et K est le checkdigit du barcode.
    2. Scanner un second barcode qui lui est l'ean13 propre au fournisseur pour l'article en question (c'est celui qui là qui est dans PDI).


    Avec ça, le programme qui calcule le prix final d'un article peut faire la différence entre deux articles ayant le même barcode grâce au premier barcode que la caissière scanne.

    Et c'est même pire que ça, chez certains fournisseurs, les références d'articles ne sont même pas uniques en interne. Ils ont donc des articles différents avec le même barcode. Je me demande comment ils s'y retrouvent mais bon, pas notre problème. Nous quand ils nous passent une liste d'article avec les pourcentages, s'il y a des doublons, on prend le pourcentage le plus élevé

    Comme ça tu sais tout.

  6. #6
    Membre expérimenté
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Par défaut
    Ah tiens, je remarque que les lignes supprimées par le trigger dans PDI constituaient les seules lignes d'articles pour un pourcentage, je dois supprimer la ligne du pourcentage dans PED sinon l'application pense que c'est un pourcentage globale... (et on risque avec 2 pourcentages globaux différents )

    Si j'ajoute un trigger AFTER DELETE (en oubliant pas de préciser DELETE ), le trigger AFTER INSERT le déclenchera-t-il ? J'ai toujours des doutes dans les interactions entre triggers.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 4
    Dernier message: 20/06/2007, 17h03
  2. [MySQL] Récuperation de données dans un boucle via une requête PHP
    Par bodysplash007 dans le forum PHP & Base de données
    Réponses: 4
    Dernier message: 19/04/2007, 11h39
  3. [MySQL] alimenter une liste déroulante via une requête
    Par stefon dans le forum PHP & Base de données
    Réponses: 2
    Dernier message: 13/12/2006, 13h32
  4. Réponses: 2
    Dernier message: 09/06/2006, 14h38
  5. Récupurer via une requête SQL la valeur la plus proche
    Par yoda_style dans le forum Langage SQL
    Réponses: 9
    Dernier message: 27/04/2004, 13h52

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