36

我在表格中有一行我不想被更改(永远)。

是否可以将 MySQL 行设置为 READ-ONLY 以使其无法以任何方式更新?如果是这样,怎么做?

如果不是,是否可以在该行的其中一列中设置一个永久值以使其无法更改?如果是这样,怎么做?

谢谢。

4

1 回答 1

41

这可能是业务逻辑,可能不属于您的数据存储层。但是,它仍然可以使用触发器来完成。

BEFORE UPDATE如果“锁定”记录即将更新,您可以创建引发错误的触发器;由于在执行操作之前发生错误,因此 MySQL 停止处理它。如果您还想防止记录被删除,您需要创建一个类似的触发器BEFORE DELETE

要确定记录是否“锁定”,您可以创建一个布尔locked列:

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 ...;

请注意,这SIGNAL是在 MySQL 5.5 中引入的。在早期版本中,您必须执行一些导致 MySQL 引发错误的错误操作:我经常调用一个不存在的过程,例如CALL raise_error;


我无法在此表上创建附加列,但该行在其中一列中具有唯一 id,那么我将如何针对这种情况执行此操作?

同样,如果您绝对必须将此逻辑放在存储层中——并且无法通过 PK 以外的任何方式识别锁定的记录——您可以将测试硬编码到触发器中;例如,要“锁定”记录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 ;

但这绝对是可怕的,我几乎会做任何事情来避免它。

于 2012-05-08T16:12:40.047 回答