Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Triggern und aktualisieren Sie eine Zeile in SQL Server, nachdem sie aktualisiert wurde

inserted ist eine Pseudo-Tabelle und enthält definitiv alle richtigen Zeilen, die vom UPDATE betroffen waren Anweisung (und ich nehme an DISTINCT ist nicht notwendig, wenn ID ein Primärschlüssel - obwohl es schwierig ist zu sagen, was die Tabelle mit einem Namen wie 121s ist ). Ob sie sich tatsächlich alle verändert hatten Werte ist eine weitere Sache, die Sie prüfen sollten, bevor Sie das geänderte Datum/die geänderte Uhrzeit anwenden. Abgesehen davon würde ich es wahrscheinlich so machen:

ALTER TRIGGER [dbo].[trg_121s] 
ON [dbo].[121s]
AFTER UPDATE
AS 
BEGIN
  SET NOCOUNT ON;

  UPDATE t SET modified = CURRENT_TIMESTAMP
   FROM dbo.[121s] AS t
   WHERE EXISTS (SELECT 1 FROM inserted WHERE ID = t.ID);
   -- WHERE EXISTS is same as INNER JOIN inserted AS i ON t.ID = i.ID;
END
GO

Wenn Sie eine 100 % narrensichere Garantie haben möchten, dass sie alle mit demselben Zeitstempel aktualisiert werden (obwohl ich nicht weiß, ob ich in diesem Anwendungsfall jemals mehrere Werte gesehen habe):

ALTER TRIGGER [dbo].[trg_121s] 
ON [dbo].[121s]
AFTER UPDATE
AS 
BEGIN
  SET NOCOUNT ON;

  DECLARE @ts DATETIME;
  SET @ts = CURRENT_TIMESTAMP;

  UPDATE t SET modified = @ts
   FROM dbo.[121s] AS t
  INNER JOIN inserted AS i 
  ON t.ID = i.ID;
END
GO

Und wenn Sie sicherstellen möchten, dass die Aktualisierung nur erfolgt, wenn beispielsweise die Spalte foo Wert geändert, könnte man sagen:

  UPDATE t SET modified = @ts
   FROM dbo.[121s] AS t
   INNER JOIN inserted AS i
   ON t.ID = i.ID
   AND t.foo <> i.foo;

Das ist das allgemeine Muster, aber es wird komplexer, wenn foo ist nullable, da SQL Server nicht in der Lage sein wird, Zeilen abzugleichen, bei denen eine Seite einen Wert hat und die andere nicht (oder beide nicht). In diesem Fall würden Sie Folgendes tun:

   AND 
   (
     t.foo <> i.foo
     OR (t.foo IS NULL AND i.foo IS NOT NULL)
     OR (t.foo IS NOT NULL AND i.foo IS NULL)
   );

Einige Leute sagen "Ich kann COALESCE oder ISNULL einfach gegen einen magischen Wert verwenden" wie folgt:

WHERE COALESCE(t.foo, 'magic') <> COALESCE(i.foo, 'magic')

...und ich warne Sie davor, weil Sie ständig nach einem magischen Wert suchen werden, der in den Daten nicht existieren kann.