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

alt*_*nqa 30 mysql constraint

甚至有可能吗?

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

我的理解是,出于数据完整性的目的,应该在数据库层应用这些类型的约束,但我找不到一种干净的、广泛接受的方法 - 这是一个我最好这样做的用例吗在应用层?

理想的方法是在普通 SQL 中执行此操作,以便不知道使用什么数据库平台,因为这可能会发生变化,但我意识到这可能要求太多,所以如果它有要依赖于平台,最好使用一些 MySQL。

谢谢!

mus*_*cio 44

我看到至少有两种方法可以实现这一点。第一种方法是不对这些一次性表授予DELETEUPDATE特权,或者就此而言,除了INSERT和之外的任何特权SELECT,因此只允许用户插入或从中选择。此选项没有性能开销,因为权限检查是任何语句处理的一部分,但它可以被具有提升权限的用户覆盖,例如root.

另一种选择是在这些表上定义BEFORE UPDATEBEFORE DELETE触发器,并使用SIGNAL触发器主体中的语句引发异常,这将分别阻止更新和删除。您将为此付出轻微的性能损失,但也会增加一些安全性,因为即使是特权用户也无法在不禁用或删除触发器的情况下克服错误。

  • 我会推荐这两种选择,因为你明确了你的意图,并且必须采取多种故意的行动来违反它 (6认同)
  • 触发器是更好的选择,因为它们会触发所有事务,包括由管理用户执行的事务,并且可以提供更具体的错误消息。 (3认同)

iHa*_*ter 11

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

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

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

  • 从[这里](https://dev.mysql.com/doc/refman/5.7/en/replace.html)来看,“REPLACE”似乎是一种“UPDATE”!“REPLACE 的工作方式与 INSERT 完全相同,只是如果表中的旧行与 PRIMARY KEY 或 UNIQUE 索引的新行具有相同的值,则在插入新行之前先删除旧行。请参阅第 13.2.5 节,“插入语法”。” (2认同)

Wer*_*rCD 9

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

数据库设计:时间点架构

在大多数关系数据库实现中。更新和删除命令会破坏发出之前存在的数据。但是,某些系统要求永远不要从数据库中物理删除或更新任何信息。在本文中,Arthur Fuller 以 Point-in-Time 架构的形式提出了针对此需求的解决方案:一种数据库设计,它允许用户重新创建数据库的图像,就像它在之前的任何时间点存在一样,而不会破坏当前图像。

时态数据库

来自维基百科的免费百科全书
时间数据库存储与时间实例相关的数据。它提供时间数据类型并存储与过去、现在和未来时间相关的信息。

两者的基本思想是,您要么需要在不删除的情况下添加数据 - 要么以这样的方式存储数据,即您可以提取当前存在的数据......或在先前的日期时间存在的数据。

相关问题在这里: how-to-create-a-point-in-time-architecture-in-mysql