2010-08-26 28 views
12

Tôi có 2 bảng: commentscomments_likes.Thực hiện truy vấn trong mysql mà không cần kích hoạt trình kích hoạt (Cách vô hiệu hóa trình kích hoạt)


comments

id  
message 
likes 

gây:

SAU DELETE

DELETE FROM comments_likes WHERE comment_id = OLD.id; 

comments_likes

id   
comment_id 

gây:

SAU INSERT

UPDATE comments SET likes = likes + 1 WHERE comments.id = NEW.comment_id; 

SAU DELETE

UPDATE comments SET likes = likes - 1 WHERE comments.id = OLD.comment_id; 

SAU CẬP NHẬT

**omited code, updates comments** 

Vì vậy, câu hỏi là, tôi có thể vô hiệu hóa các trigger khi kích hoạt chúng từ một cò?

Những gì tôi muốn là làm điều gì đó thích này:

SAU DELETE

IF NOT called_from_another_trigger() THEN 
    UPDATE comments SET likes = likes - 1 WHERE comments.id = OLD.comment_id; 
END IF; 

[EDIT]

Một giải pháp không được tối ưu hóa sẽ được (rất chậm truy vấn ... tạo truy vấn cho mỗi đăng ký LIKE):

BEGIN 
    IF (SELECT id FROM comments WHERE comments.id = OLD.comment_id) THEN 
     UPDATE comments SET comments.cache_likes = comments.cache_likes - 1 WHERE comments.id = OLD.comment_id; 
    END IF; 
END 

CẬP NHẬT LOW PRIORITYIGNORE không hoạt động.

[EDIT 2]

Tôi có ý tưởng khác, có thể thiết lập một biến toàn cầu trong kích hoạt đầu tiên và đọc nó từ cò khác?

Ex:

đầu tiên kích hoạt:

@disable_triggers = true; 
// do the stuff that calls another triggers 
@disable_triggers = false; 

kích hoạt khác:

if @disable_triggers = false then 
    // do the stuff 
end if; 

Trả lời

21

Để vô hiệu hoá gây nên bạn có thể làm:

Kích hoạt 1

SET @disable_trigger = 1; 
// do stuff that calls trigger 2 
SET @disable_trigger = NULL; 

Kích hoạt 2

IF @disable_trigger IS NULL THEN 
    // do stuff only if called from a query and not from trigger 1 
END IF; 
+0

Ineresting! Bạn có thực sự vô hiệu hóa trình kích hoạt bên trong trình kích hoạt không? – Mchl

+1

@Mchl: Vâng, với phương pháp này bạn có thể :) @var là các hình cầu cho kết nối. Bạn phải sử dụng IS NULL vì các biến chưa được định nghĩa luôn là NULL. – Wiliam

+1

điều này đã giúp tôi 4 năm sau! tôi đã chính xác tìm kiếm một cái gì đó như thế này. sau 1 giờ googling và tìm kiếm SO, cuối cùng tôi đã tìm thấy câu trả lời của bạn. thật dễ dàng, nhưng tôi không bao giờ tự mình tìm ra được. tôi chỉ không được sử dụng để có thể "chương trình" với mysql. –

0

Không bạn không thể. Đó là điểm gây nên: luôn chạy.

Ngoài ra, tôi không thể biết lý do bạn cần điều đó trong trường hợp của bạn. Tại tồi tệ nhất không có gì được cập nhật - không có lỗi sẽ được nâng lên.

Bạn luôn có thể thêm điều kiện vào trình kích hoạt, để kiểm tra xem chúng (hoặc một phần mã của chúng) có được chạy hay không (ví dụ: nếu có bản ghi trong bảng có liên quan).

+0

Khi bạn cố gắng xóa nhận xét, trình kích hoạt sẽ xóa tất cả các lượt thích. Khi lượt thích bị xóa, chúng sẽ cập nhật nhận xét đã bị xóa. Một thông báo lỗi xuất hiện: 'Không thể cập nhật bảng 'bình luận' trong chức năng/trình kích hoạt được lưu trữ vì nó đã được sử dụng bởi câu lệnh đã gọi hàm/trigger được lưu trữ này – Wiliam

+0

@Wiliam: Vâng, với điều kiện tôi có thể làm điều đó ... nhưng không phải là giải pháp tôi đã tìm kiếm uu – Wiliam

+0

@ Mchl có lẽ đó là điểm của các trigger, nhưng trong MySQL chúng không phải lúc nào cũng được thực thi. Nếu một hàng bị xóa vì CASCADE thực thi ràng buộc khóa ngoài, thì không có trình kích hoạt nào được thực thi. Tham khảo: [Tài liệu MySQL] (http://dev.mysql.com/doc/refman/5.6/en/create-table-foreign-keys.html). Tôi mạnh mẽ tin rằng nguồn gốc của hạn chế này của MySQL có cùng một lý do gốc là lỗi trong bình luận của William. –

1

Có thể là một chút xấu xí, nhưng những gì tôi làm là đổi tên bảng đến table2 mà kích hoạt không đính kèm quá, và sau đó, vào cuối, đổi tên trở lại.

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