我的问题是关于 MySQL 数据库中的参照完整性概念。由于我们的 DBA 的某种限制,我们不允许使用 MySQL 的参照完整性功能,所以我的问题是“当我们在 MySQL 中没有参照完整性功能时,我们如何在 MySQL 中实现外键概念?”
谢谢。
我的问题是关于 MySQL 数据库中的参照完整性概念。由于我们的 DBA 的某种限制,我们不允许使用 MySQL 的参照完整性功能,所以我的问题是“当我们在 MySQL 中没有参照完整性功能时,我们如何在 MySQL 中实现外键概念?”
谢谢。
我假设您使用的是 MyISAM 表?你几乎坚持自己做检查。
因此,如果 tableB 依赖于 tableA,那么在从 tableA 中删除之前,您必须先从 tableB 中删除(或执行其他更新)。使用插入,您将在主表中创建记录,然后在从属表中创建记录。
这很麻烦,我发现保存 MyISAM 表的唯一原因是 FULLTEXT 索引。如果我对您的数据库限制有更多了解,我可能会提出其他建议。
预计到达时间:
如果他限制您使用 InnoDB 表,我想知道您的 DBA。无论如何,如果出于安全原因他不允许您创建和使用 Innodb 表,那么他真的不太可能让您使用存储过程或触发器。因此,您基本上会被困在编写应用程序以使用某种脚本语言执行CRUD操作。
因此,您需要考虑针对每种特定情况对这些操作的限制。可能最简单的方法是映射您的数据库模式,就好像它确实强制了引用完整性一样。包括有关由于任何表的更改而可能发生的操作(如果有)的详细信息。操作后遗症选项有 RESTRICT、SET NULL 和 CASCADE。
一旦你知道你的数据库应该如何响应,你就可以对你的查询进行相应的编程。
因此,如果员工有地址,并且在删除员工时地址应该消失:
Innodb 版本(地址具有员工的外键和ON DELETE CASCADE
操作)
DELETE FROM Employees WHERE employee_id=7;
MyISAM 版本:
DELETE FROM Employees WHERE employee_id=7;
DELETE FROM Addresses WHERE employee_id=7;
我希望这能让事情变得更清楚一些。
这意味着所有开发人员必须特别了解应该存在的关系,并且在执行插入或更新时从父表向下通过所有子表工作,在执行删除时从子表向上通过父表工作。当然,问题是不是每个开发人员都会意识到约束中涉及的所有表都没有设置。如果你有多层关系,你需要一直到链的底部进行删除。
如果您使用 ORM,我认为您可以在那里定义关系?不确定从未使用过,但我认为您可以。无论如何都值得研究。
如果您不使用 ORM 并且无法定义参照完整性,那么至少将关系存储在某个表中,以便开发人员可以查找哪些表会受到影响。
如果您无法具体定义参照完整性,另一种方法是通过触发器强制执行它。
编辑以扩展触发器:如果您在父表上创建而不是触发器(这些在我的 sql 中可用吗?),您可以通过在执行实际删除之前指定要删除的表来模仿级联删除的行为(这如何在我们进行级联删除之前,我们曾经这样做过)。如果主键在更新中更改,您还可以指定要更新的表(希望您的设计具有不会更改的键,但如果您使用任何自然键则不会更改)。任何子表上的插入触发器都会查看键字段值是否存在于父表中,如果不存在则拒绝它。
我曾经使用 myIsam 表。
因此,这意味着您需要手动完成这项工作。例如,您需要在删除某些父行之前执行一些 SELECT。
这是可能的,但没有参考完整性是不一样的。但有效。
如果可能使用存储过程来使“选择”更容易。另一个好的方法是将数据库模式隐藏在模型后面,并通过它的接口使用它。
在这种情况下,DBA 经常听到的一个论点是“如果使用 RI,那么卸载/加载以进行重组对我们来说更难”。
就其本身而言,这当然是正确的,但问题在于,“更难”通常被认为是指“如此困难,以至于我们 DBA 几乎不可能完成我们的工作”。
那是公牛。
有一些持久性框架可以为你做这件事。为了在尽可能多的数据库上工作,这些框架不依赖于数据库特定功能(如 FK)并自行实现它们。KODO就是一个例子。