Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Jak zapobiec aktualizacjom tabeli, z wyjątkiem jednej sytuacji

Dlaczego nie użyć INSTEAD OF cyngiel? Wymaga trochę więcej pracy (a mianowicie powtarzania UPDATE oświadczenie), ale za każdym razem, gdy możesz uniemożliwić pracę, zamiast pozwolić jej się wydarzyć, a następnie ją wycofać, wyjdzie ci lepiej.

CREATE TRIGGER [dbo].[Item_BeforeUpdate_AnyBilled]
ON [dbo].[Item]
INSTEAD OF UPDATE
AS 
BEGIN
  SET NOCOUNT ON;

  IF EXISTS 
  (
     SELECT 1 FROM inserted i
       JOIN deleted AS d ON i.ItemId = d.ItemId
       WHERE d.BillId IS NULL -- it was NULL before, may not be NULL now
  )
  BEGIN
     UPDATE src 
       SET col1 = i.col1 --, ... other columns
          ModifiedDate = CURRENT_TIMESTAMP -- this eliminates need for other trigger
       FROM dbo.Item AS src
       INNER JOIN inserted AS i
       ON i.ItemId = src.ItemId
       AND (criteria to determine if at least one column has changed);
  END
  ELSE
  BEGIN
     RAISERROR(...);
  END
END
GO

To nie pasuje idealnie. Kryteria, które pominąłem, zostały pominięte z jakiegoś powodu:ustalenie, czy wartość kolumny uległa zmianie, może być skomplikowane, ponieważ zależy to od typu danych, czy kolumna może mieć wartość NULL itp. AFAIK wbudowane funkcje wyzwalacza może tylko stwierdzić, czy określona kolumna została określona, ​​a nie, czy wartość rzeczywiście zmieniła się w stosunku do poprzedniej.

EDYTUJ biorąc pod uwagę, że martwisz się tylko innymi kolumnami, które są aktualizowane z powodu wyzwalacza po, myślę, że następujące INSTEAD OF wyzwalacz może zastąpić oba istniejące wyzwalacze, a także obsługiwać wiele wierszy aktualizowanych jednocześnie (niektóre bez spełniania kryteriów):

CREATE TRIGGER [dbo].[Item_BeforeUpdate_AnyBilled]
ON [dbo].[Item]
INSTEAD OF UPDATE
AS 
BEGIN
  SET NOCOUNT ON;

  UPDATE src SET col1 = i.col1 --, ... other columns,
     ModifiedDate = CURRENT_TIMESTAMP
     FROM dbo.Item AS src
     INNER JOIN inserted AS i
     ON src.ItemID = i.ItemID
     INNER JOIN deleted AS d
     ON i.ItemID = d.ItemID 
     WHERE d.BillID IS NULL; 

  IF @@ROWCOUNT = 0
  BEGIN
    RAISERROR(...);
  END
END
GO



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak zamienić wartości null na nieznane w instrukcji Select w SQL Server — samouczek SQL Server / TSQL, część 111

  2. Jaki jest najlepszy sposób tworzenia i wypełniania tabeli liczb?

  3. Jak uzyskać informacje statystyczne programu SQL Server za pomocą funkcji statystycznych systemu?

  4. W tabeli odniesienia nie ma kluczy podstawowych ani kandydujących, które pasują do listy kolumn odniesienia w kluczu obcym

  5. Jak zmienić tabelę w SQL Server za pomocą instrukcji Alter — SQL Server / samouczek T-SQL, część 35