2009-01-10 53 views
17

Giả sử bạn có các bảng PresentationsEvents. Khi bản trình bày được lưu và chứa thông tin sự kiện cơ bản, chẳng hạn như vị trí và ngày, sự kiện sẽ được tạo tự động bằng trình kích hoạt. (Tôi e rằng không thể vì lý do kỹ thuật chỉ đơn giản là giữ dữ liệu ở một nơi và sử dụng chế độ xem.) Ngoài ra, khi thay đổi thông tin này sau trong bản trình bày, trình kích hoạt cũng sẽ sao chép các bản cập nhật cho sự kiện đó, như vậy:Ngăn chặn việc thực thi đệ quy đệ quy?

CREATE TRIGGER update_presentations 
ON Presentations 
AFTER UPDATE 
AS 
BEGIN 
    UPDATE Events 
    SET Events.Date = Presentations.Date, 
     Events.Location = Presentations.Location 
    FROM Presentations INNER JOIN Events ON Presentations.EventID = Events.ID 
    WHERE Presentations.ID IN (SELECT ID FROM inserted) 
END 

Bây giờ, khách hàng muốn nó như vậy đó, nếu người dùng không bao giờ thay đổi thông tin trong kiện, nó nên trở về trình bày là tốt. Vì lý do hiển nhiên, tôi không thể làm ngược lại:

CREATE TRIGGER update_events 
ON Events 
AFTER UPDATE 
AS 
BEGIN 
    UPDATE Presentations 
    SET Presentations.Date = Events.Date, 
     Presentations.Location = Events.Location 
    FROM Events INNER JOIN Presentations ON Events.PresentationID = Presentations.ID 
    WHERE Events.ID IN (SELECT ID FROM inserted) 
END 

Sau khi tất cả, điều này sẽ khiến mỗi kích hoạt kích hoạt lẫn nhau. Những gì tôi có thể làm là thêm một cột last_edit_by vào cả hai bảng, chứa ID người dùng. Nếu lấp đầy bởi cò với một ID hợp lệ đặc biệt (ví dụ, bằng cách làm cho tất cả các ID người dùng của người thực tế tích cực, nhưng ID người dùng của kịch bản tiêu cực), tôi có thể sử dụng như là một điều kiện xuất cảnh:

AND last_edit_by >= 0 

này có thể làm việc , nhưng những gì tôi muốn làm là chỉ ra cho máy chủ SQL rằng, trong một giao dịch, một kích hoạt chỉ nên kích hoạt một lần. Có cách nào để kiểm tra điều này không? Hoặc có lẽ để kiểm tra xem một bảng đã bị ảnh hưởng bởi một kích hoạt?


trả lời nhờ Steve Robbins:

Chỉ cần quấn khả năng lồng UPDATE báo cáo trong một điều kiện IF kiểm tra trigger_nestlevel(). Ví dụ:

CREATE TRIGGER update_presentations 
ON Presentations 
AFTER UPDATE 
AS 
BEGIN 
    IF trigger_nestlevel() < 2 
     UPDATE Events 
     SET Events.Date = Presentations.Date, 
      Events.Location = Presentations.Location 
     FROM Presentations INNER JOIN Events ON Presentations.EventID = Events.ID 
     WHERE Presentations.ID IN (SELECT ID FROM inserted) 
END 

Lưu ý rằng trigger_nestlevel() có vẻ là dựa trên 1, không dựa trên 0. Nếu bạn muốn một trong hai trình kích hoạt thực hiện một lần, nhưng không thường xuyên hơn, chỉ cần kiểm tra trigger_nestlevel() < 3 trong cả hai trình kích hoạt.

Trả lời

18

Tôi không chắc chắn về việc thực hiện nó cho mỗi giao dịch, nhưng bạn có cần kích hoạt lồng nhau được bật cho các phần khác không? Nếu bạn tắt chúng trên máy chủ thì trình kích hoạt sẽ không kích hoạt từ trình kích hoạt khác đang cập nhật bảng.

EDIT (câu trả lời từ các ý kiến): Bạn sẽ cần phải thay đổi kích hoạt A sử dụng TRIGGER_NESTLEVEL

+0

trigger lồng nhau đang thực sự vô hiệu hóa trên cơ sở dữ liệu đó. Vấn đề của tôi là trường hợp kích hoạt A bắn B bắn A, không phải A bắn A trực tiếp. Cài đặt không ngăn điều này. –

+0

Thats trigger đệ quy, tôi không phải ở một máy tại thời điểm này nhưng tôi chắc chắn rằng có lồng nhau gây nên quá mà bạn có thể cấu hình với sp_config. Đã được một vài năm kể từ khi tôi phải đối mặt với vấn đề này mặc dù. –

+0

Bạn nói đúng; kích hoạt lồng nhau là một tùy chọn khác. Nhưng cách tôi đọc tài liệu của nó, nó sẽ ngăn chặn B bắn sau khi A, trong khi tôi muốn ngăn chặn A bắn lần thứ hai. –