web-dev-qa-db-fra.com

Comment puis-je modifier les valeurs d'un INSERT dans un déclencheur sur SQL Server?

J'ai la table Tb

ID | Name   | Desc
-------------------------
 1 | Sample | sample desc

Je veux créer un déclencheur sur INSERT qui changera la valeur de l'insertion Desc, par exemple:

INSERT INTO Tb(Name, Desc) VALUES ('x', 'y')

Aura pour résultat

ID | Name   | Desc
-------------------------
 1 | Sample | sample desc
 2 | x      | Y edited

Dans l'exemple ci-dessus, j'ai obtenu la valeur de l'insertion Desc, je l'ai changé en majuscule et j'ai ajouté edited à la fin.

C'est ce dont j'ai besoin, récupérez le Desc qui est inséré et modifiez-le.

Comment puis je faire ça?

Est-il préférable de le gérer après l'insertion avec une mise à jour? Ou faire un déclencheur avec INSTEAD OF INSERT et le modifier à chaque fois que la structure de la table change?

29
BrunoLM

Utilisez un déclencheur après insertion. Joignez la pseudo-table inserted à Tb sur la clé primaire. Mettez ensuite à jour les valeurs de desc. Quelque chose comme: (mais peut ne pas compiler)

CREATE TRIGGER TbFixTb_Trg 
ON  Tb  
AFTER INSERT 
AS  
BEGIN 
    UPDATE Tb
    SET DESC = SomeTransformationOf(i.DESC)
    FROM Tb
    INNER JOIN inserted i on i.Id = Tb.Id
END  
GO

Ce déclencheur se produit après l'insertion, mais avant la fin de l'instruction insert. Ainsi, les nouvelles valeurs incorrectes sont déjà placées dans la table cible. Ce déclencheur n'aura pas besoin de changer lorsque des colonnes sont ajoutées, supprimées, etc.

Avertissement Les contraintes d'intégrité sont appliquées avant le déclenchement du déclencheur après. Vous ne pouvez donc pas appliquer de contrainte de vérification pour appliquer la forme appropriée de DESC. Parce que cela entraînerait l'échec de l'instruction avant que le déclencheur ait la possibilité de corriger quoi que ce soit. (Veuillez vérifier ce paragraphe avant de vous y fier. Cela fait un moment que je n'ai pas écrit de déclencheur.)

38
Shannon Severance

Je ne sais pas où vous allez obtenir la nouvelle valeur réelle pour desc, mais je suppose que vous l'obtenez à partir d'une autre table ou d'une telle. Mais vous avez probablement une raison de vouloir le faire de cette façon, voici donc un exemple de la façon dont je procéderais.

Ce que vous voulez s'appelle un déclencheur INSTEAD OF INSERT, il se déclenche au lieu d'un insert sur la table avec ce que chaque logique que vous lui donnez.

CREATE TRIGGER trgUpdateDesc
ON  Tb 
INSTEAD OF INSERT
AS 
BEGIN
    SET NOCOUNT ON;
    INSERT INTO Tb (Name, [Desc])
    SELECT Name, [Desc] + 'edited'
    FROM inserted
END 
GO

J'ai codé en dur le mot "édité" là-dedans car je ne sais pas où vous voulez obtenir la valeur, mais vous pouvez facilement le remplacer par une variable ou une valeur d'une autre table.

Oh, assurez-vous également de mettre le [] autour de Desc, car il s'agit d'un mot clé dans le serveur sql (signifie descendant)

J'espère que cela pourra aider!

Éditer:

Si vous voulez le rendre un peu plus robuste pour qu'il ne dépende pas autant de la structure de la table, vous pouvez utiliser un déclencheur AFTER INSERT pour simplement mettre à jour ce champ comme ça.

CREATE TRIGGER [dbo].[trgUpdateDesc]
   ON  [dbo].[Tb] 
   AFTER INSERT
AS 
BEGIN
    SET NOCOUNT ON;
    UPDATE Tb
    SET [Desc] = UPPER(inserted.[Desc]) +  ' Edited'
    FROM inserted INNER JOIN Tb On inserted.id = Tb.id
END 
26
JonVD

La table temporaire peut aider à utiliser INSTEAD OF INSERT déclencher en évitant de lister explicitement toutes les colonnes de table non liées:

CREATE TRIGGER trgUpdateDesc
    ON Tb 
    INSTEAD OF INSERT
AS 
BEGIN
    SET NOCOUNT ON;
    select * into #tmp from inserted;
    UPDATE #tmp SET Desc = Desc + 'edited' --where ...;
    insert into Tb select * from #tmp;
    drop table #tmp;
END 

Ce code n'aura pas besoin d'être corrigé lorsque de nouvelles colonnes sont ajoutées à la table.

Mais méfiez-vous de certains frais généraux supplémentaires des tables temporaires .

Notez également que les déclencheurs SQL Server se déclenchent une fois pour les opérations DML en bloc et doivent gérer correctement les insertions sur plusieurs lignes .

9
Vadzim

Vous voudrez peut-être regarder INSTEAD OF déclenche.

CREATE TRIGGER Tb_InsteadTrigger on Tb
INSTEAD OF INSERT
AS
BEGIN
...

Cela vous permettra de manipuler les données avant qu'elles n'entrent dans la table. Le déclencheur est responsable de l'insertion des données dans la table.

4
bobs