Yalnızca gerçek değişikliklere neden olan bir T-SQL Tetikleyici nasıl yapılır?


9

UPDATE ve başka bir tabloya bir satır ekler INSERT bir tablo tetikleyicisi var . Yalnızca dört sütundan biri değiştirildiğinde satır eklemesi gerekir. Değişiklikleri test etmek için IF UPDATE (col) kullanarak denedim ama kör bir nokta var. Sadece bazı değerlerin geldiğini test eder. Daha derine inmem gerekiyor, gerçek bir değişiklik olduğunu görmek için eski ve yeni değerleri karşılaştırmam gerekiyor. INSERT ve UPDATE ile birlikte çalışması gerekir.

Hem UPDATE hem de silinen tabloların tetikleyici içinde karşılaştırabileceğim değerlere sahip olması nedeniyle bu kolay bir UPDATE durumunda. Ancak, INSERT için yalnızca ekleme tablosunun değerleri vardır. Tüm bunlara aynı tetikleyicide ihtiyacım olduğu için, INSERT vakasını nasıl ele alabilirim?

İşte değiştirmek istediğiniz tetikleyicinin komut dosyası:

ALTER TRIGGER [dbo].[trATPerson_alter] 
   ON  [mydb].[dbo].[AT_Person]
   AFTER INSERT,UPDATE
AS 
BEGIN
    SET NOCOUNT ON;

    -- Not all updates require a push
    IF (UPDATE([First_Name]) OR UPDATE([Last_Name]) OR UPDATE([JobCode]) OR UPDATE([Inactive]))
    BEGIN
        INSERT INTO [mydb].[dbo].[AT_Person_To_Push] (
                [Facility],
                [VendorID],
                [Person_code],
                [First_Name],
                [Last_Name],
                [JobCode],
                [Alink],
                [Inactive]
            )
        SELECT  [Facility],
                [VendorID],
                [Person_code],
                [First_Name],
                [Last_Name],
                [JobCode],
                [Alink],
                [Inactive]
        FROM inserted 
    END
END

2
"IF UPDATE (<column>)" kullanımı hakkında kısa bir kelime. DML, değerin gerçekten değişip değişmediğine bakılmaksızın, sütun için bir değer belirtirse true değerini döndürür.
Jonathan Fite

Yanıtlar:


18

INSERT ve UPDATE öğelerini EXCEPT ayarlanmış bir işleçle işleyebilirsiniz. EXISTS, yalnızca yalnızca bir INSERT ise veya bu sütunlardan herhangi biri için farklı değerlere sahip bir GÜNCELLEME ise DOĞRU olarak değerlendirilir.

IF EXISTS (
           SELECT First_Name, Last_Name, JobCoe, Inactive FROM inserted
           EXCEPT
           SELECT First_Name, Last_Name, JobCoe, Inactive FROM deleted
          )
BEGIN...

Bu, sütun güncellenmiş çeşitli işlevlere bakmaktan çok daha zariftir. Bazı ön uç koduna sahip olanları yalnızca değişen değerleri göndermek için birleştirdik (çok fazla boğulduktan sonra). Bir EXCEPT kullanmak çok daha mantıklı.
Peter Schott

2
Bu, bir güncellemede 2 satırın "değiştirildiği" durumlarda çalışmaz. JobCodes'larının güncellenmesi gereken iki John Smith'imiz varsa (ilk John 1'den 2'ye; ikinci John 2'den 1'e) - bu güncelleme yapılmadığını söyler.
Steven Hibble

2
@StevenHibble - Mümkünse bunun gerçekleşmesi ne kadar olası? Bu durum, yukarıdaki Select deyimlerine PK sütunları eklenerek kolayca çözülebilir.
Chad Estes

1
Olasılığın veri kaynağına ve kötü veri girişi olasılığına bağlı olduğunu söyleyebilirim. "Hata, yanlış John Smith ..." hiçbir zaman olmayacakmış gibi görünüyor . Her durumda, bu çok satırlı bir güncelleştirmenin diğer yarısını ele almaz: yalnızca değişen satırları eklediğinizden nasıl emin olabilirsiniz? Bu EXISTS, herhangi bir satırın değişip değişmediğini kontrol eder . Eklemeyi sorudan uzak tutarsanız, yalnızca bir tanesi anlamlı bir şekilde değiştiğinde güncellenen tüm satırları günlüğe kaydedersiniz.
Steven Hibble

2

Bir güncellemenin birden çok satırı etkileyebilmesi durumunda, iki şeye karşı korunmanız gerekir:

  1. Değerleri benzer satırlar arasında değiştiren güncellemeleri dikkate almak istiyoruz. JobCodes'larının güncellenmesi gereken iki John Smith varsa (ilk John 1'den 2'ye; ikinci John 2'den 1'e), her ikisinin de güncellendiğini söylememize dikkat etmeliyiz.
  2. Yalnızca değiştirilen satırları girmek istiyoruz AT_Person_To_Push. 5 satır güncellenir, ancak önem verdiğimiz şekilde yalnızca 2 satır güncellenirse, yalnızca 2 ilgili satırı işlememiz gerekir.

İşte nasıl ele alacağım:

  1. Sol katılmak insertediçin deletedçünkü insertediken ekler ve güncellemeler için satır olacak deletedsadece güncellemeleri için satır olacak.
  2. Değerlerin değerlerden farklı olduğu satırları bulmak için EXISTSile kullanın . Tetikleyici bir INSERT işlerken silinen tablo boş olacağından (ve SOL BİRLEŞME boş değer döndüreceği için) kullanamazsınız .EXCEPTinserteddeletedi.First_Name != d.First_Name OR i.Last_Name != d.Last_Name...
  3. Yalnızca etkilenen satırları içine ekleyin AT_Person_To_Push.
ALTER TRIGGER [dbo].[trATPerson_alter] 
   ON  [mydb].[dbo].[AT_Person]
   AFTER INSERT,UPDATE
AS 
BEGIN
    SET NOCOUNT ON;

    INSERT INTO [mydb].[dbo].[AT_Person_To_Push] (
            [Facility],
            [VendorID],
            [Person_code],
            [First_Name],
            [Last_Name],
            [JobCode],
            [Alink],
            [Inactive]
        )
    SELECT  i.[Facility],
            i.[VendorID],
            i.[Person_code],
            i.[First_Name],
            i.[Last_Name],
            i.[JobCode],
            i.[Alink],
            i.[Inactive]
    FROM inserted i
         LEFT JOIN deleted d
           ON i.Person_code = d.Person_code
    -- Check for changes that require a push
    WHERE EXISTS (SELECT i.[First_Name], i.[Last_Name], i.[JobCode], i.[Inactive]
                  EXCEPT
                  SELECT d.[First_Name], d.[Last_Name], d.[JobCode], d.[Inactive]);
END

1

Bunu dene,

Declare @Acton int=0

If exists (Select 1 from inserted)
set @Acton=1

If exists (Select 1 from deleted)
set @Acton=@Acton+2

if(@Action=1) -- Only insert

if(@Action=3) -- Only Update
begin
IF (UPDATE([First_Name]) OR UPDATE([Last_Name]) OR UPDATE([JobCode]) OR UPDATE([Inactive]))
Begin

End
end

if(@Action=2) -- Only Delete
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.