Sqlserver
 sql >> Teknologi Basis Data >  >> RDS >> Sqlserver

Bagaimana mencegah pembaruan ke tabel, dengan pengecualian untuk satu situasi

Mengapa tidak menggunakan INSTEAD OF pemicu? Ini membutuhkan sedikit lebih banyak pekerjaan (yaitu UPDATE berulang-ulang pernyataan) tetapi setiap kali Anda dapat mencegah pekerjaan, alih-alih membiarkannya terjadi dan kemudian memutarnya kembali, Anda akan menjadi lebih baik.

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

Ini tidak cocok. Kriteria yang saya tinggalkan diabaikan karena suatu alasan:dapat menjadi rumit untuk menentukan apakah nilai kolom telah berubah, karena bergantung pada tipe data, apakah kolom dapat berupa NULL, dll. AFAIK fungsi pemicu bawaan hanya dapat mengetahui apakah kolom tertentu telah ditentukan, bukan apakah nilainya benar-benar berubah dari sebelumnya.

EDIT mengingat Anda hanya peduli dengan kolom lain yang diperbarui karena pemicu setelahnya, saya pikir INSTEAD OF berikut pemicu dapat menggantikan kedua pemicu yang ada dan juga menangani beberapa baris yang diperbarui sekaligus (beberapa tanpa memenuhi kriteria Anda):

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. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Ubah varchar menjadi datetime di SQL Server

  2. Peningkatan Layanan Broker di SQL Server 2016

  3. Kemungkinan Cara untuk Memperbaiki Masalah Korupsi Metadata SQL Server

  4. Menemukan Induk Tingkat Teratas di SQL

  5. Apa itu Format String di SQL Server?