sql >> Database >  >> RDS >> Sqlserver

Hoe u updates van een tabel kunt voorkomen, met een uitzondering voor één situatie?

Waarom gebruik je geen INSTEAD OF trekker? Het vereist wat meer werk (namelijk een herhaalde UPDATE verklaring) maar elke keer dat je werk kunt voorkomen, in plaats van het te laten gebeuren en het vervolgens terug te draaien, ben je beter af.

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

Dit past niet perfect. De criteria die ik heb weggelaten, zijn om een ​​​​reden weggelaten:het kan ingewikkeld zijn om te bepalen of een kolomwaarde is gewijzigd, omdat dit afhangt van het gegevenstype, of de kolom NULL kan zijn, enz. AFAIK de ingebouwde triggerfuncties kan alleen zien of een bepaalde kolom is opgegeven, niet of de waarde daadwerkelijk is gewijzigd ten opzichte van voorheen.

BEWERKEN aangezien u zich alleen zorgen maakt over de andere kolommen die worden bijgewerkt vanwege de after-trigger, denk ik dat het volgende INSTEAD OF trigger kan beide bestaande triggers vervangen en kan ook omgaan met meerdere rijen die tegelijk worden bijgewerkt (sommige zonder aan uw criteria te voldoen):

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. hoe een opgeslagen proc van helmknop te bellen en de refcursor te wijzigen die wordt geretourneerd?

  2. Hoe gebruik je meerdere WITH-statements in één PostgreSQL-query?

  3. Genereer datumbereik uit twee datumkolommen

  4. Altijd een database nodig voor je app?