sql >> Database teknologi >  >> RDS >> Sqlserver

Sådan forhindrer du opdateringer til en tabel, med en undtagelse for én situation

Hvorfor ikke bruge en INSTEAD OF udløser? Det kræver lidt mere arbejde (nemlig en gentagen UPDATE statement), men hver gang du kan forhindre arbejde, i stedet for at lade det ske og derefter rulle det tilbage, vil du have det bedre.

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

Dette passer ikke perfekt. Kriterierne jeg har udeladt er udeladt af en grund:det kan være komplekst at afgøre om en kolonneværdi har ændret sig, da det afhænger af datatypen, om kolonnen kan være NULL osv. AFAIK den indbyggede triggerfunktioner kan kun se, om en bestemt kolonne var angivet, ikke om værdien faktisk ændrede sig fra før.

REDIGER i betragtning af at du kun er bekymret for de andre kolonner, der opdateres på grund af efter-triggeren, tror jeg følgende INSTEAD OF trigger kan erstatte begge dine eksisterende triggere og også håndtere flere rækker opdateret på én gang (nogle uden at opfylde dine kriterier):

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. Oprettelse af visuel database med MySQL Workbench

  2. MySQL brugerstyring

  3. hvordan udføres et .sql-script på heroku?

  4. SQLite - ORDER BY RAND()