如何在SQL中强制执行一次写入然后只读的数据库表?


28

可能吗

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

我的理解是,出于数据完整性的目的,应将这些类型的约束应用于数据库层,但是我找不到一种干净的,被广泛接受的方式来做这—这是一个用例,我会做得更好在应用层?

理想的方法是在普通的SQL中执行此操作,以便与使用的数据库平台无关,因为这可能会发生变化,但是我意识到这可能要求太多,因此是否需要为了与平台相关,首选MySQL的某种风格。

谢谢!

Answers:


43

我看到至少有两种方法可以做到这一点。第一种方法是不授予DELETE,并UPDATE在这些一次性写入表,或,对于这个问题,除了从任何特权的特权INSERTSELECT,因此只允许用户插入或从中选择。

另一个选择是在这些表上定义BEFORE UPDATEBEFORE DELETE触发,并使用该SIGNAL语句在触发主体中引发异常,这将分别阻止更新和删除。


6
我建议您使用这两种方法,因为您要清楚表明自己的意图,并且必须采取多种故意行动来违反它
Adam Martin

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

10

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

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

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


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

7

查看“ 时间点架构 ”或“ 时间数据库架构

数据库设计:时间架构中的一个点

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

时态数据库

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

两者的基本思想是,您要么需要添加数据而不删除它们,要么以某种方式存储数据,以便可以提取当前存在的数据...或以前的日期时间存在的数据。

这里的相关问题: 如何在mysql中创建时间点架构

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.