2012-08-27 32 views
70

Bằng cách xem các ví dụ khác tôi đã đưa ra các ví dụ sau nhưng dường như không hoạt động như tôi muốn: Tôi muốn nó chỉ cập nhật thông tin đã sửa đổi nếu giá trị QtyToRepair đã được cập nhật ... nhưng nó không làm điều đó.Kích hoạt cập nhật SQL chỉ khi cột được sửa đổi

Nếu tôi nhận xét nơi mà thông tin được sửa đổi được cập nhật trong mọi trường hợp. Như tôi đã nói các ví dụ khác đã khiến tôi lạc quan. Bất kỳ manh mối nào được đánh giá cao. Cảm ơn.

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 
+1

DB gì bạn đang sử dụng? –

+1

loooks như máy chủ sql –

+7

Cảnh báo về 'update()' - nó chỉ kiểm tra xem cột có xuất hiện trong danh sách cập nhật hay không và luôn đúng đối với chèn. Nó không kiểm tra nếu giá trị cột đã thay đổi, bởi vì bạn có thể có nhiều hơn một hàng, trong đó một số giá trị đã thay đổi và một số giá trị không thay đổi. –

Trả lời

93

Bạn có hai cách cho câu hỏi của bạn:

1- Sử dụng lệnh Update trong trình kích hoạt của bạn.

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- Sử dụng Tham giữa bảng chèn và bảng xóa

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 

Khi bạn sử dụng lệnh cập nhật cho bảng SCHEDULE và Set QtyToRepair Cột giá trị mới, nếu giá trị mới bằng giá trị cũ trong một hoặc đa hàng, giải pháp 1 cập nhật tất cả các hàng cập nhật trong bảng lịch biểu nhưng giải pháp 2 cập nhật chỉ lịch hàng mà giá trị cũ không bằng giá trị mới.

+0

Xin lỗi vì đã không đề cập đến đó là SQLServer. Tôi cần sử dụng bảng đã xóa. Tôi đã kết thúc bằng văn bản cho một bảng riêng biệt (để duy trì một lịch sử). –

+5

Phương pháp tiếp cận # 2 tốt hơn, nếu bạn không muốn kích hoạt của mình kích hoạt nếu cột đang được thay đổi thành cùng một giá trị. – Neolisk

+0

Tôi nghĩ rằng tôi có thể thiếu một cái gì đó - nhưng cách tiếp cận # 1 sẽ không hoạt động, bởi vì đây là * sau * cập nhật, do đó hàng hiện tại sẽ luôn có cùng giá trị với hàng chèn. Bạn * phải * tham gia xóa nếu bạn đang sử dụng sau khi cập nhật – Rob

5

Bạn muốn làm như sau:

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 

Xin lưu ý rằng kích hoạt này sẽ cháy mỗi khi bạn cập nhật các cột không có vấn đề nếu giá trị là như nhau hay không.

11

Bạn nên kiểm tra xem QtyToRepair có được cập nhật lúc đầu không.

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 
10

FYI Mã tôi đã kết thúc với:

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 
+1

Tôi thấy điều này hữu ích vì câu trả lời ** 2 Tham gia Sử dụng giữa ** ở trên không bao giờ hoạt động do nơi tiêu chí 'WHERE S.QtyToRepair <> I.QtyToRepair VÀ D.QtyToRepair <> I.QtyToRepair' không bao giờ kích hoạt/khớp với tiêu chí đầu tiên không bao giờ đúng - bảng được chèn luôn khớp với giá trị bảng thực tế. Sử dụng 'WHERE I.QtyToRepair <> D.QtyToRepair' là chìa khóa cho tôi. Ngoài ra, 'IF UPDATE (field)' trợ giúp từ nhiều trigger gây ra. – Firegarden

Các vấn đề liên quan