sql >> Databáze >  >> RDS >> Sqlserver

Jak zabránit aktualizacím tabulky, s výjimkou pro jednu situaci

Proč nepoužít INSTEAD OF spoušť? Vyžaduje to trochu více práce (jmenovitě opakované UPDATE prohlášení), ale kdykoli můžete zabránit práci, místo abyste ji nechali, aby se stala a pak ji vrátila zpět, budete na tom lépe.

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

Tohle se úplně nehodí. Kritéria, která jsem vynechal, jsou z nějakého důvodu vynechána:může být složité určit, zda se hodnota sloupce změnila, protože závisí na datovém typu, zda sloupec může být NULL atd. AFAIK vestavěné spouštěcí funkce může zjistit pouze to, zda byl zadán určitý sloupec, nikoli to, zda se hodnota skutečně změnila oproti předchozímu.

UPRAVIT vzhledem k tomu, že vás znepokojují pouze ostatní sloupce, které jsou aktualizovány kvůli spouštěči po, myslím, že následující INSTEAD OF spouštěč může nahradit oba vaše stávající spouštěče a také se vypořádat s několika aktualizovanými řádky najednou (některé, aniž by splňovaly vaše kritéria):

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. Rychlý tip – Zrychlete pomalé obnovení z protokolu transakcí

  2. Příklady LAST_DAY() – MySQL

  3. Jak Atan() funguje v PostgreSQL

  4. KNIME