none
TRIGGER AFTER/FOR DELETE Problem RRS feed

  • Question

  • Salut, actuellement je travaille sur mon projet de fin d'étude et j'ai un problème avec l'utilisation des trigger.

    J'ai deux Table: TableX et TableXHistory ou j'ai besoin que le TRIGGER fait une insertion des données de la Table TableX vers TableXHistroy et cela a chaque suppression.

    Sachant que mes Tables: TableX et TableXHistory ont une clé primaire composée.

    Voici le code du trigger:

    CREATE TRIGGER MyTrigger
    ON dbo.Table
    FOR DELETE  /*J'ai même essayé avec AFTER DELETE aussi et j'ai pas trouver de différence*/
    AS
    	BEGIN
    		DECLARE 
    			@Col1 NVARCHAR(50),
    			@Col2 NVARCHAR(50),
    			@Col3 NVARCHAR(50)
    		
    	         SELECT 
                               @Col1 = Col1 ,
                               @Col2 = Col2,
                               @Col3= Col13
    
                     FROM Deleted
    		
                     INSERT INTO dbo.TableXHistory VALUES(@Col1,@Col2,@Col3)
    
    	END

    Bon sur ma table: TableX j'execute une requête qui va supprimer +de 1000lignes, et je veux que le trigger les insert dans la table TableXHistroy mais j'ai qu'une seule ligne qui est inséré.

    Tandis que si je fait un SELECT et je récupère les lignes a supprimer et je fait un DELETE pour chaqu'une, le TRIGGER fonctionne correctement et cela prend beaucoup de temps.

    Info:

    WINDOWS 8, SQLSERVER 2012 (Express), VISUAL STUDIO 2012

    Merci d'avance :)

    • Déplacé Naomi N mardi 16 avril 2013 16:04 Better answer can be here
    mardi 16 avril 2013 12:17

Réponses

  • A common misconception is that the trigger fires for each row.  If that were true, your code would work fine.  However the trigger fires once for the DELETE statement, meaning only one trigger execution for 1 row, but also only one trigger execution for 1000 rows.

    So your code is using variables that can only hold a single value.  What you should do inside your procedure is code for an unknown number of rows.  The following should work:

    INSERT INTO dbo.TableXHistory (Col1, Col2, Col3)
    SELECT Col1, Col2, Col3 FROM deleted

    This INSERT will receive all of the rows that you SELECT from deleted, whether 1 or 1000.  Does that make sense to you?

    RLF

    PS Google Translate:    Une idée fausse commune est que le déclencheur est lancé pour chaque ligne. Si cela était vrai, votre code va fonctionner très bien. Toutefois, le déclencheur se déclenche une fois pour l'instruction DELETE, ce qui signifie une seule exécution du déclencheur pour 1 rangée, mais aussi une seule exécution du déclencheur pour 1000 lignes.

    Ainsi, votre code utilise des variables qui ne peut contenir qu'une seule valeur. Ce que vous devez faire dans votre procédure est un code pour un nombre indéterminé de lignes. Ce qui suit devrait fonctionner:

    Cet insert recevrez toutes les lignes que vous sélectionnez supprimé, si 1 ou 1000. Est-ce logique pour vous?

    • Proposé comme réponse Naomi N mardi 16 avril 2013 16:04
    • Marqué comme réponse nadjibnet jeudi 18 avril 2013 09:31
    mardi 16 avril 2013 13:17

Toutes les réponses

  • A common misconception is that the trigger fires for each row.  If that were true, your code would work fine.  However the trigger fires once for the DELETE statement, meaning only one trigger execution for 1 row, but also only one trigger execution for 1000 rows.

    So your code is using variables that can only hold a single value.  What you should do inside your procedure is code for an unknown number of rows.  The following should work:

    INSERT INTO dbo.TableXHistory (Col1, Col2, Col3)
    SELECT Col1, Col2, Col3 FROM deleted

    This INSERT will receive all of the rows that you SELECT from deleted, whether 1 or 1000.  Does that make sense to you?

    RLF

    PS Google Translate:    Une idée fausse commune est que le déclencheur est lancé pour chaque ligne. Si cela était vrai, votre code va fonctionner très bien. Toutefois, le déclencheur se déclenche une fois pour l'instruction DELETE, ce qui signifie une seule exécution du déclencheur pour 1 rangée, mais aussi une seule exécution du déclencheur pour 1000 lignes.

    Ainsi, votre code utilise des variables qui ne peut contenir qu'une seule valeur. Ce que vous devez faire dans votre procédure est un code pour un nombre indéterminé de lignes. Ce qui suit devrait fonctionner:

    Cet insert recevrez toutes les lignes que vous sélectionnez supprimé, si 1 ou 1000. Est-ce logique pour vous?

    • Proposé comme réponse Naomi N mardi 16 avril 2013 16:04
    • Marqué comme réponse nadjibnet jeudi 18 avril 2013 09:31
    mardi 16 avril 2013 13:17
  • Thank's I'll try it and i'll give you the result
    mardi 16 avril 2013 15:10
  • Bonjour,

    Est-ce que vous avez testé les solutions proposées ? Merci de partager avec nous les résultats, afin que d'autres personnes avec le même problème puissent profiter de cette solution.

    Cordialement,


    Aurel BERA, Microsoft
    Microsoft propose ce service gratuitement, dans le but d'aider les utilisateurs et d'élargir les connaissances générales liées aux produits et technologies Microsoft. Ce contenu est fourni "tel quel" et il n'implique aucune responsabilité de la part de Microsoft.

    jeudi 18 avril 2013 09:14
    Modérateur
  • Parfait cela fonctionne a merveille je vous remercie infiniment.
    jeudi 18 avril 2013 09:30
  • Bonjour;

    après quelques mois je passe sur la question, une autre solution pourrais résoudre le problème (que j'utilise souvent).

    l'idée est que dans la requête dans le programme client on peut spécifié si le résultat de la suppression va être affecter à une table 

    DELETE "Nom_Table"
        OUTPUT DELETED.* into "Nom_Table_Cible"
        where ..... (clause where de la suppression)

    mercredi 31 juillet 2013 01:25