【问题标题】:How to set a MySQL row to READ-ONLY?如何将 MySQL 行设置为只读?
【发布时间】:2012-05-17 03:42:08
【问题描述】:

我不想(永远)更改表格中的一行。

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

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

谢谢。

【问题讨论】:

  • 不,不存在只读行。但是您可以设置 MySQL 帐户,使特定用户没有更新/删除权限。
  • @Marc B:所以我提到的两个选项都不可用?请确认,因为很遗憾您提到的用户权限解决方案无法解决我的问题。
  • @Kris:根本不是那个问题的重复。我的问题完全不同。
  • @Rahul:我需要更新表中的其他行,所以这不是一个选项。

标签: mysql sql database


【解决方案1】:

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

您可以创建一个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 ;

但这太可怕了,我会做任何事情尽可能避免它。

【讨论】:

  • 感谢您提供非常有趣的解决方案。我无法在此表上创建额外的列,但该行在其中一列中具有唯一 id,那么我将如何针对这种情况执行此操作?
  • @Programmer:只需在触发器的IF 语句中测试idIF OLD.column &lt;=&gt; 'unique_id' THEN ...
  • 现在有一个非正统的解决方案。我喜欢。 +1 请记住,尽管您在 mysql 中只能有一个触发器(每个表的每个事件),所以如果您已经拥有或将来需要另一个触发器......您必须将它们组合成一个。
  • @eggyal:好的。三个问题:1)什么是“”? 2) 什么是“旧”? 3)什么是“分隔符;;” ?再次感谢!
  • @Programmer:&lt;=&gt;NULL-安全相等比较运算符; OLDNEW 是触发器中可用的关键字,可在操作之前/之后提供对受影响记录值的访问 - 请参阅 Trigger SyntaxDELIMITER 指定了一个新的语句分隔符,以便将本身包含常用 ; 分隔符的命令视为单个语句 - 如果您愿意,可以选择 ;; 以外的字符序列。
猜你喜欢
  • 1970-01-01
  • 2013-08-26
  • 2020-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多