Đây có thể là logic nghiệp vụ, có thể không thuộc lớp lưu trữ dữ liệu của bạn. Tuy nhiên, nó vẫn có thể được thực hiện bằng cách sử dụng trình kích hoạt .
Bạn có thể tạo BEFORE UPDATE
kích hoạt gây ra lỗi nếu bản ghi "bị khóa" sắp được cập nhật; vì một lỗi xảy ra trước đó hoạt động được thực hiện, MySQL ngừng tiếp tục với nó. Nếu bạn cũng muốn ngăn bản ghi bị xóa, bạn cần tạo một trình kích hoạt tương tự BEFORE DELETE
.
Để xác định xem một bản ghi có bị "khóa" hay không, bạn có thể tạo một boolean locked
cột:
ALTER TABLE my_table ADD COLUMN locked BOOLEAN NOT NULL DEFAULT FALSE;
DELIMITER ;;
CREATE TRIGGER foo_upd BEFORE UPDATE ON my_table FOR EACH ROW
IF OLD.locked THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Cannot update locked record';
END IF;;
CREATE TRIGGER foo_del BEFORE DELETE ON my_table FOR EACH ROW
IF OLD.locked THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Cannot delete locked record';
END IF;;
DELIMITER ;
UPDATE my_table SET locked = TRUE WHERE ...;
Lưu ý rằng SIGNAL
đã được giới thiệu trong MySQL 5.5. Trong các phiên bản trước đó, bạn phải thực hiện một số hành động sai khiến MySQL phát sinh lỗi:Tôi thường gọi một thủ tục không tồn tại, ví dụ:với CALL raise_error;
Một lần nữa, nếu bạn hoàn toàn phải đặt logic này trong lớp lưu trữ — và không thể xác định các bản ghi bị khóa thông qua bất kỳ phương tiện nào khác ngoài PK — bạn có thể mã hóa bài kiểm tra vào trình kích hoạt của bạn; ví dụ:để "khóa" bản ghi với id_column = 1234
:
DELIMITER ;;
CREATE TRIGGER foo_upd BEFORE UPDATE ON my_table FOR EACH ROW
IF OLD.id_column <=> 1234 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Cannot update locked record';
END IF;;
CREATE TRIGGER foo_del BEFORE DELETE ON my_table FOR EACH ROW
IF OLD.id_column <=> 1234 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Cannot delete locked record';
END IF;;
DELIMITER ;
Nhưng điều này hoàn toàn kinh khủng và tôi sẽ làm hầu hết mọi thứ để tránh nó bất cứ khi nào có thể.