Pemicu pembaruan SQL hanya jika kolom diubah

101

Dengan melihat contoh lain, saya mendapatkan yang berikut tetapi tampaknya tidak berfungsi seperti yang saya inginkan: Saya ingin itu hanya memperbarui informasi yang dimodifikasi jika QtyToRepairnilainya telah diperbarui ... tetapi tidak berhasil bahwa.

Jika saya berkomentar di mana maka informasi yang dimodifikasi diperbarui dalam setiap kasus. Seperti yang saya katakan, contoh lain membuat saya optimis. Setiap petunjuk dihargai. Terima kasih.

Walter

ALTER TRIGGER [dbo].[tr_SCHEDULE_Modified]
   ON [dbo].[SCHEDULE]
   AFTER UPDATE
AS 
BEGIN
    SET NOCOUNT ON;

    UPDATE SCHEDULE SET modified = GETDATE()
        , ModifiedUser = SUSER_NAME()
        , ModifiedHost = HOST_NAME()
    FROM SCHEDULE S
    INNER JOIN Inserted I on S.OrderNo = I.OrderNo and S.PartNumber = I.PartNumber
    WHERE S.QtyToRepair <> I.QtyToRepair
END
Walter de Jong
sumber
8
Peringatan tentang update()- ini hanya menguji jika kolom muncul dalam daftar pembaruan, dan selalu benar untuk sisipan. Itu tidak memeriksa apakah nilai kolom telah berubah, karena Anda mungkin memiliki lebih dari satu baris, di mana beberapa nilai telah berubah dan beberapa tidak.
Nikola Markovinović

Jawaban:

128

Ada dua cara untuk pertanyaan Anda:

1- Gunakan Perintah Pembaruan di Pemicu Anda.

ALTER TRIGGER [dbo].[tr_SCHEDULE_Modified]
   ON [dbo].[SCHEDULE]
   AFTER UPDATE
AS BEGIN
    SET NOCOUNT ON;
    IF UPDATE (QtyToRepair) 
    BEGIN
        UPDATE SCHEDULE 
        SET modified = GETDATE()
           , ModifiedUser = SUSER_NAME()
           , ModifiedHost = HOST_NAME()
        FROM SCHEDULE S INNER JOIN Inserted I 
        ON S.OrderNo = I.OrderNo and S.PartNumber = I.PartNumber
        WHERE S.QtyToRepair <> I.QtyToRepair
    END 
END

2- Gunakan Gabung antara Tabel yang disisipkan dan tabel yang dihapus

ALTER TRIGGER [dbo].[tr_SCHEDULE_Modified]
   ON [dbo].[SCHEDULE]
   AFTER UPDATE
AS BEGIN
    SET NOCOUNT ON;    

    UPDATE SCHEDULE 
    SET modified = GETDATE()
       , ModifiedUser = SUSER_NAME()
       , ModifiedHost = HOST_NAME()
    FROM SCHEDULE S 
    INNER JOIN Inserted I ON S.OrderNo = I.OrderNo and S.PartNumber = I.PartNumber
    INNER JOIN Deleted D ON S.OrderNo = D.OrderNo and S.PartNumber = D.PartNumber                  
    WHERE S.QtyToRepair <> I.QtyToRepair
    AND D.QtyToRepair <> I.QtyToRepair
END

Ketika Anda menggunakan perintah pembaruan untuk tabel SCHEDULEdan Atur QtyToRepairKolom ke nilai baru, jika nilai baru sama dengan nilai lama dalam satu atau beberapa baris, solusi 1 memperbarui semua baris yang diperbarui dalam tabel Jadwal tetapi solusi 2 memperbarui hanya menjadwalkan baris yang nilai lama tidak sama dengan yang baru nilai.

mehdi lotfi
sumber
Maaf karena tidak menyebutkan bahwa itu adalah SQLServer. Saya perlu menggunakan tabel yang dihapus. Saya akhirnya menulis ke tabel terpisah (untuk mempertahankan sejarah).
Walter de Jong
9
Pendekatan # 2 lebih baik, jika Anda tidak ingin pemicu Anda diaktifkan jika kolom diubah ke nilai yang sama.
Neolisk
2
Saya pikir saya mungkin melewatkan sesuatu - tetapi pendekatan # 1 tidak akan berfungsi, karena ini setelah pembaruan, jadi baris saat ini akan selalu memiliki nilai yang sama dengan baris penyisipan. Anda harus bergabung untuk dihapus jika Anda menggunakan setelah pembaruan
Rob
5
@Rob Pernyataan "JIKA UPDATE" menjalankan prosedur yang memiliki akses ke daftar kolom kolom yang diperbarui sebagai bagian dari kueri dan dengan demikian tidak perlu mengetahui nilai sebelumnya. (Kami baru saja menemukan ini di lingkungan kami dan mengonfirmasi bahwa "JIKA PEMBARUAN" tetap berlaku terlepas dari klausul "SETELAH PEMBARUAN")
TChadwick
3
mengapa Anda menggabungkan insertedtabel di kueri kedua? itu harus sama dengan tabel itu sendiri, bukan?
teran
22

fyi Kode yang saya dapatkan:

IF UPDATE (QtyToRepair)
    begin
        INSERT INTO tmpQtyToRepairChanges (OrderNo, PartNumber, ModifiedDate, ModifiedUser, ModifiedHost, QtyToRepairOld, QtyToRepairNew)
        SELECT S.OrderNo, S.PartNumber, GETDATE(), SUSER_NAME(), HOST_NAME(), D.QtyToRepair, I.QtyToRepair FROM SCHEDULE S
        INNER JOIN Inserted I ON S.OrderNo = I.OrderNo and S.PartNumber = I.PartNumber
        INNER JOIN Deleted D ON S.OrderNo = D.OrderNo and S.PartNumber = D.PartNumber 
        WHERE I.QtyToRepair <> D.QtyToRepair
end
Walter de Jong
sumber
1
Saya menemukan ini membantu karena 2- Gunakan Gabungan antara jawaban di atas tidak pernah berfungsi karena kriteria di mana WHERE S.QtyToRepair <> I.QtyToRepair AND D.QtyToRepair <> I.QtyToRepairtidak pernah aktif / cocok karena kriteria pertama tidak pernah benar - tabel yang dimasukkan selalu cocok dengan nilai tabel yang sebenarnya. Menggunakan `WHERE I.QtyToRepair <> D.QtyToRepair` adalah kuncinya bagi saya. Juga IF UPDATE (field)bantuan dari beberapa pemicu penembakan.
Firegarden
13

Seseorang harus memeriksa apakah QtyToRepairdiperbarui pada awalnya.

ALTER TRIGGER [dbo].[tr_SCHEDULE_Modified]
   ON [dbo].[SCHEDULE]
   AFTER UPDATE
AS 
BEGIN
SET NOCOUNT ON;
    IF UPDATE (QtyToRepair) 
    BEGIN
        UPDATE SCHEDULE 
        SET modified = GETDATE()
           , ModifiedUser = SUSER_NAME()
           , ModifiedHost = HOST_NAME()
        FROM SCHEDULE S INNER JOIN Inserted I 
            ON S.OrderNo = I.OrderNo and S.PartNumber =    I.PartNumber
        WHERE S.QtyToRepair <> I.QtyToRepair
    END
END
hgulyan
sumber
6

Anda ingin melakukan hal berikut:

ALTER TRIGGER [dbo].[tr_SCHEDULE_Modified]
   ON [dbo].[SCHEDULE]
   AFTER UPDATE
AS 
BEGIN
SET NOCOUNT ON;

    IF (UPDATE(QtyToRepair))
    BEGIN
        UPDATE SCHEDULE SET modified = GETDATE()
            , ModifiedUser = SUSER_NAME()
            , ModifiedHost = HOST_NAME()
        FROM SCHEDULE S
        INNER JOIN Inserted I ON S.OrderNo = I.OrderNo AND S.PartNumber = I.PartNumber
        WHERE S.QtyToRepair <> I.QtyToRepair
    END
END

Harap dicatat bahwa pemicu ini akan aktif setiap kali Anda memperbarui kolom tidak peduli apakah nilainya sama atau tidak.

Carlos Vergara
sumber
2

Setiap kali catatan telah diperbarui, catatan akan "dihapus". Inilah contoh saya:

ALTER TRIGGER [dbo].[UpdatePhyDate]
   ON  [dbo].[M_ContractDT1]
   AFTER UPDATE
AS 
BEGIN
    -- on ContarctDT1 PhyQty is updated 
    -- I want system date in Phytate automatically saved
    SET NOCOUNT ON;

    declare @dt1ky as int   

    if(update(Phyqty))
    begin
        select @dt1ky = dt1ky from deleted

        update M_ContractDT1 set PhyDate=GETDATE() where Dt1Ky=  @dt1ky     

    end

END

Ini bekerja dengan baik

Mohamed Yazeer
sumber