毫不犹豫地对数据库施加约束。您一定会拥有一个一致的数据库,这是使用数据库的充分理由之一。特别是如果您有多个应用程序请求它(或只有一个应用程序,但具有直接模式和使用不同来源的批处理模式)。
使用 MySQL,您不会像在 postgreSQL 中那样拥有高级约束,但至少外键约束非常高级。
我们举个例子,一个公司表和一个用户表,其中包含来自这些公司的人
CREATE TABLE COMPANY (
company_id INT NOT NULL,
company_name VARCHAR(50),
PRIMARY KEY (company_id)
) ENGINE=INNODB;
CREATE TABLE USER (
user_id INT,
user_name VARCHAR(50),
company_id INT,
INDEX company_id_idx (company_id),
FOREIGN KEY (company_id) REFERENCES COMPANY (company_id) ON...
) ENGINE=INNODB;
让我们看看ON UPDATE子句:
-
ON UPDATE RESTRICT:默认值:如果您尝试更新表 COMPANY 中的 company_id,如果一个用户至少链接到该公司,引擎将拒绝该操作。
-
ON UPDATE NO ACTION:与 RESTRICT 相同。
-
ON UPDATE CASCADE:通常是最好的:如果您在 COMPANY 表的一行中更新 company_id,引擎将在引用该 COMPANY 的所有 USER 行上相应地更新它(但没有在 USER 表上激活的触发器,警告)。引擎会为您跟踪更改,这很好。
-
ON UPDATE SET NULL :如果您在 COMPANY 表的一行中更新 company_id,引擎会将相关的 USERs company_id 设置为 NULL(应该在 USER company_id 字段中可用)。我在更新中看不到任何有趣的事情,但我可能错了。
现在在 ON DELETE 方面:
-
ON DELETE RESTRICT:默认值:如果您尝试删除表 COMPANY 中的 company_id Id,如果一个 USER 至少链接到该公司,引擎将拒绝该操作,可以保存你的生活。
-
ON DELETE NO ACTION:与 RESTRICT 相同
-
ON DELETE CASCADE:危险:如果您删除表 COMPANY 中的公司行,引擎也会删除相关的 USER。这很危险,但可用于对辅助表进行自动清理(因此它可以是您想要的,但对于 COMPANYUSER 示例肯定不是)
-
ON DELETE SET NULL : handful : 如果您删除 COMPANY 行,相关的 USER 将自动与 NULL 建立关系。如果 Null 是您对没有公司的用户的价值,这可能是一种很好的行为,例如,您可能需要将用户保留在您的应用程序中,作为某些内容的作者,但删除公司对您来说不是问题。
通常我的默认设置是:ON DELETE RESTRICT ON UPDATE CASCADE。有一些ON DELETE CASCADE 用于跟踪表(日志——不是所有日志——,类似的东西)和ON DELETE SET NULL,当主表是包含外键的表的“简单属性”时,比如 JOB 表USER 表。
编辑
很久没写了。现在我想我应该添加一个重要的警告。 MySQL 对级联有一个很大的记录限制。 级联不会触发触发器。因此,如果您对该引擎有足够的信心使用触发器,则应避免级联约束。
MySQL 触发器仅针对 SQL 语句对表所做的更改激活。它们不会因视图的更改而激活,也不会因不将 SQL 语句传输到 MySQL 服务器的 API 对表的更改而激活
==> 见下方最后的编辑,这个域正在发生变化
外键操作不会激活触发器。
而且我认为这不会有一天会得到解决。外键约束由 InnoDb 存储管理,触发器由 MySQL SQL 引擎管理。两者是分开的。 Innodb 是唯一有约束管理的存储,也许有一天他们会直接在存储引擎中添加触发器,也许不会。
但是我有我自己的观点,你应该在糟糕的触发器实现和非常有用的外键约束支持之间选择哪个元素。一旦你习惯了数据库的一致性,你就会爱上 PostgreSQL。
12/2017-更新此关于 MySQL 的编辑:
正如@IstiaqueAhmed 在 cmets 中所说,这个问题的情况已经发生了变化。因此,请点击链接并查看真实的最新情况(将来可能会再次更改)。