我的用例是一个分类帐表,要求创建记录后,该记录应该是只读的,即没有人可以编辑或删除它。这仅适用于分类帐表和与之有直接关系的表-同一模式中还有其他表将按常规更新/删除。

我的理解是,出于数据完整性的目的,这些各种各样的约束应该应用于数据库层,但是我找不到一种干净的,被广泛接受的方式来做到这一点-这是一个用例,我会更好地在应用程序层中做到这一点?
理想的方法是在普通的SQL中执行此操作,以便与使用的数据库平台无关,因为这可能会发生变化,但是我意识到可能要求太多,因此,如果必须依赖于平台,则首选使用MySQL的某种形式。

谢谢!

#1 楼

我看到至少有两种方法可以实现这一目标。第一种方法是不授予这些一次写入表DELETEUPDATE特权,或者就此而言,不授予INSERTSELECT之外的任何特权,因此仅允许用户插入或从中选择。此选项没有性能开销,因为特权检查是任何语句处理的一部分,但是可以由具有更高特权的用户(例如root)覆盖。
另一个选项是在这些表上定义BEFORE UPDATEBEFORE DELETE触发器在触发器主体中使用SIGNAL语句引发异常,该异常将分别防止更新和删除。您需要为此付出一点性能损失,但是还要增加一些安全性,因为即使是特权用户也无法在不禁用或删除触发器的情况下克服错误。

评论


我建议您同时使用这两种方法,因为您必须清楚说明自己的意图,并且必须采取多项故意措施来违反它

–亚当·马丁(Adam Martin)
17年11月21日在22:50

触发器是更好的选择,因为它们会触发所有事务,包括管理用户执行的事务,并且会给出更具体的错误消息。

– Blfl
17年11月22日在12:11

#2 楼

权限似乎是显而易见的选择-但是您也可以使用ARCHIVE存储引擎。此表引擎旨在记录不会更改的大量数据:


ARCHIVE引擎支持INSERT,REPLACE和SELECT,但不支持DELETE或UPDATE。它确实支持ORDER BY操作,BLOB列以及除空间数据类型以外的所有类型(请参见第11.5.1节“空间数据类型”)。 ARCHIVE引擎使用行级锁定。


权限的区别在于,具有扩展特权的人仍然可以更改大多数其他表类型上的数据,而ARCHIVE不允许任何人更改表中已经存在的数据。

评论


从这里开始,REPLACE似乎是一种UPDATE! “ REPLACE的工作原理与INSERT完全相同,不同之处在于,如果表中的旧行与PRIMARY KEY或UNIQUE索引的新行具有相同的值,则在插入新行之前删除该旧行。请参见第13.2.5节。 ,“插入语法”。

–Vérace
17年11月22日在6:42



#3 楼

查看“时间点体系结构”或“时态数据库体系结构”

数据库设计:时间点体系结构



在大多数关系数据库实现中。更新和删除命令会销毁发布前的数据。但是,某些系统要求
绝不从
数据库中物理删除或更新任何信息。在本文中,Arthur Fuller以时间点体系结构的形式提出了解决此需求的解决方案:一种数据库设计,允许用户在创建数据库图像时重新创建它。
/>在以前的任何时间点都存在,而不会破坏当前的图像。


时间数据库


从Wikipedia,免费的百科全书
时态数据库存储与时间实例有关的数据。它提供时态数据类型并存储与过去,现在和将来时间有关的信息。


两者的基本思想是,您需要添加数据而不删除-或以这种方式存储数据一种可以提取当前存在的数据或以前的日期时间存在的数据的方法。

此处的相关问题:如何在时间架构中创建点在mysql中,