Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

Cách ngăn cập nhật bảng, trừ một trường hợp ngoại lệ

Tại sao không sử dụng INSTEAD OF cò súng? Nó yêu cầu nhiều công việc hơn một chút (cụ thể là UPDATE lặp lại tuyên bố) nhưng bất cứ lúc nào bạn có thể ngăn cản công việc, thay vì để nó xảy ra và sau đó quay trở lại, bạn sẽ tốt hơn.

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

Điều này không hoàn toàn phù hợp. Tiêu chí tôi đã bỏ qua bị bỏ qua vì một lý do:có thể phức tạp để xác định xem giá trị cột có thay đổi hay không, vì nó phụ thuộc vào kiểu dữ liệu, liệu cột đó có thể là NULL hay không, v.v. KHẮC PHỤC các hàm kích hoạt tích hợp sẵn chỉ có thể cho biết liệu một cột nhất định đã được chỉ định hay chưa, chứ không phải liệu giá trị có thực sự thay đổi so với trước đó hay không.

CHỈNH SỬA xem xét rằng bạn chỉ quan tâm đến các cột khác được cập nhật do trình kích hoạt sau, tôi nghĩ rằng INSTEAD OF sau trình kích hoạt có thể thay thế cả hai trình kích hoạt hiện tại của bạn và cũng xử lý nhiều hàng được cập nhật cùng một lúc (một số hàng không đáp ứng tiêu chí của bạn):

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. Xếp hàng trong OneWay WCF Messages bằng Windows Service và SQL Server

  2. Tạo hồ sơ công khai mặc định cho thư cơ sở dữ liệu trong SQL Server (T-SQL)

  3. Triển khai chức năng phân trang (bỏ qua / lấy) với truy vấn này

  4. Chuyển đổi số nguyên thành hex và hex thành số nguyên

  5. CURRENT_TIMESTAMP Ví dụ trong SQL Server (T-SQL)