外键约束:何时使用 ON UPDATE 和 ON DELETE

发布于 2024-11-24 03:51:00 字数 412 浏览 0 评论 0原文

我正在使用 MySQL Workbench 设计我的数据库模式,这非常酷,因为您可以绘制图表并转换它们:P

不管怎样,我决定使用 InnoDB,因为它支持外键。我注意到的一件事是,它允许您设置外键的“更新”和“删除”选项。有人可以在一个简单的例子中解释一下“Restrict”、“Cascade”和 set null 可以在哪里使用吗?

例如,假设我有一个 user 表,其中包含 userID。假设我有一个消息表message,它是一个多对多,有 2 个外键(引用相同的主键,userID) 表)。在这种情况下,设置“更新时”和“删除时”选项有用吗?如果是这样,我该选择哪一个?如果这不是一个很好的例子,您能否想出一个很好的例子来说明这些如何有用?

谢谢

I'm designing my database schema using MySQL Workbench, which is pretty cool because you can do diagrams and it converts them :P

Anyways, I've decided to use InnoDB because of it's Foreign Key support. One thing I noticed though is that it allows you to set On Update and on Delete options for foreign keys. Can someone explain where "Restrict", "Cascade" and set null could be used in a simple example?

For example, say I have a user table which includes a userID. And say I have a message table message which is a many-to-many which has 2 foreign keys (which reference the same primary key, userID in the user table). Is setting the On Update and On Delete options any useful in this case? If so, which one do I choose? If this isn't a good example, could you please come up with a good example to illustrate how these could be useful?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

度的依靠╰つ 2024-12-01 03:51:06

除了 @MarkR 答案之外 - 需要注意的一件事是,许多具有 ORM 的 PHP 框架无法识别或使用高级数据库设置(外键、级联删除、唯一约束),这可能会导致意外的行为。

例如,如果您使用 ORM 删除一条记录,并且您的 DELETE CASCADE 将删除相关表中的记录,则 ORM 尝试删除这些相关记录(通常是自动的)将导致错误。

Addition to @MarkR answer - one thing to note would be that many PHP frameworks with ORMs would not recognize or use advanced DB setup (foreign keys, cascading delete, unique constraints), and this may result in unexpected behaviour.

For example if you delete a record using ORM, and your DELETE CASCADE will delete records in related tables, ORM's attempt to delete these related records (often automatic) will result in error.

死开点丶别碍眼 2024-12-01 03:51:05

您需要在应用程序的上下文中考虑这一点。一般来说,您应该设计一个应用程序,而不是一个数据库(数据库只是应用程序的一部分)。

考虑您的应用程序应如何响应各种情况。

默认操作是限制(即不允许)操作,这通常是您想要的,因为它可以防止愚蠢的编程错误。然而,DELETE CASCADE 也很有用。这实际上取决于您的应用程序以及您打算如何删除特定对象。

就我个人而言,我会使用 InnoDB,因为它不会破坏你的数据(参见 MyISAM,它会破坏数据),而不是因为它有 FK 约束。

You'll need to consider this in context of the application. In general, you should design an application, not a database (the database simply being part of the application).

Consider how your application should respond to various cases.

The default action is to restrict (i.e. not permit) the operation, which is normally what you want as it prevents stupid programming errors. However, on DELETE CASCADE can also be useful. It really depends on your application and how you intend to delete particular objects.

Personally, I'd use InnoDB because it doesn't trash your data (c.f. MyISAM, which does), rather than because it has FK constraints.

ゝ杯具 2024-12-01 03:51:03

请毫不犹豫地对数据库施加约束。您一定会拥有一个一致的数据库,这是使用数据库的好理由之一。特别是如果您有多个应用程序请求它(或者只有一个应用程序,但具有使用不同源的直接模式和批处理模式)。

对于 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,如果一个用户至少链接到该公司,引擎将拒绝该操作。
  • 更新时不执行:与 RESTRICT 相同。
  • ON UPDATE CASCADE通常是最好的:如果您更新表 COMPANY 的一行中的 company_id,引擎将在引用该 COMPANY 的所有 USER 行上相应地更新它(但不在 USER 表上激活触发器,警告)。引擎会为你跟踪变化,这很好。
  • ON UPDATE SET NULL :如果您更新表 COMPANY 的一行中的 company_id ,引擎会将相关用户的 company_id 设置为 NULL (应该在 USER company_id 字段中可用)。我在更新中看不到任何有趣的事情,但我可能是错的。

现在在ON DELETE一侧:

  • ON DELETE RESTRICT默认:如果您尝试删除表COMPANY中的company_id Id,引擎将如果至少有一个用户链接到该公司,则拒绝该操作可以挽救您的生命。
  • ON DELETE NO ACTION :与 RESTRICT 相同
  • ON DELETE CASCADE危险:如果您删除表 COMPANY 中的公司行,引擎也会删除相关用户。这是危险的,但可以用于对辅助表进行自动清理(因此它可以是您想要的东西,但肯定不适用于 COMPANY<->USER 示例)
  • ON DELETE SET NULL : < em>handful:如果删除 COMPANY 行,相关的 USER 将自动具有 NULL 关系。如果 Null 是您对没有公司的用户的值,这可能是一个很好的行为,例如,您可能需要将用户保留在您的应用程序中,作为某些内容的作者,但删除公司对您来说不是问题。

通常我的默认设置是:ON DELETE RESTRICT ON UPDATE CASCADE。当主表是“简单属性”时,使用一些ON DELETE CASCADE用于跟踪表(日志——不是所有日志——,类似的东西)和ON DELETE SET NULL ' 对于包含外键的表,例如 USER 表的 JOB 表。

编辑

自从我写这篇文章以来已经很长时间了。现在我想我应该添加一个重要警告。 MySQL 在级联方面有一个大的记录限制。 级联不会触发触发器。因此,如果您对该引擎有足够的信心来使用触发器,则应该避免级联约束。

MySQL 触发器仅在 SQL 语句对表进行的更改时激活。它们不会因视图的更改而激活,也不会因不将 SQL 语句传输到 MySQL 服务器的 API 对表所做的更改而激活

==>请参阅下面的最后一次编辑,该域上的事情正在发生变化

触发器不是由外键操作激活的。

我认为这个问题不会有一天得到解决。外键约束由 InnoDb 存储管理,触发器由 MySQL SQL 引擎管理。两者都分开了。 Innodb是唯一具有约束管理的存储,也许有一天他们会直接在存储引擎中添加触发器,也许不会。

但对于应该在糟糕的触发器实现和非常有用的外键约束支持之间选择哪个元素,我有自己的看法。一旦您习惯了数据库一致性,您就会喜欢 PostgreSQL。

12/2017-更新有关 MySQL 的编辑:

正如 @IstiaqueAhmed 在评论中所述,这个主题的情况已经发生了变化。因此,请点击链接并检查真实的最新情况(将来可能会再次发生变化)。

Do not hesitate to put constraints on the database. You'll be sure to have a consistent database, and that's one of the good reasons to use a database. Especially if you have several applications requesting it (or just one application but with a direct mode and a batch mode using different sources).

With MySQL you do not have advanced constraints like you would have in postgreSQL but at least the foreign key constraints are quite advanced.

We'll take an example, a company table with a user table containing people from theses company

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;

Let's look at the ON UPDATE clause:

  • ON UPDATE RESTRICT : the default : if you try to update a company_id in table COMPANY the engine will reject the operation if one USER at least links on this company.
  • ON UPDATE NO ACTION : same as RESTRICT.
  • ON UPDATE CASCADE : the best one usually : if you update a company_id in a row of table COMPANY the engine will update it accordingly on all USER rows referencing this COMPANY (but no triggers activated on USER table, warning). The engine will track the changes for you, it's good.
  • ON UPDATE SET NULL : if you update a company_id in a row of table COMPANY the engine will set related USERs company_id to NULL (should be available in USER company_id field). I cannot see any interesting thing to do with that on an update, but I may be wrong.

And now on the ON DELETE side:

  • ON DELETE RESTRICT : the default : if you try to delete a company_id Id in table COMPANY the engine will reject the operation if one USER at least links on this company, can save your life.
  • ON DELETE NO ACTION : same as RESTRICT
  • ON DELETE CASCADE : dangerous : if you delete a company row in table COMPANY the engine will delete as well the related USERs. This is dangerous but can be used to make automatic cleanups on secondary tables (so it can be something you want, but quite certainly not for a COMPANY<->USER example)
  • ON DELETE SET NULL : handful : if you delete a COMPANY row the related USERs will automatically have the relationship to NULL. If Null is your value for users with no company this can be a good behavior, for example maybe you need to keep the users in your application, as authors of some content, but removing the company is not a problem for you.

usually my default is: ON DELETE RESTRICT ON UPDATE CASCADE. with some ON DELETE CASCADE for track tables (logs--not all logs--, things like that) and ON DELETE SET NULL when the master table is a 'simple attribute' for the table containing the foreign key, like a JOB table for the USER table.

Edit

It's been a long time since I wrote that. Now I think I should add one important warning. MySQL has one big documented limitation with cascades. Cascades are not firing triggers. So if you were over confident enough in that engine to use triggers you should avoid cascades constraints.

MySQL triggers activate only for changes made to tables by SQL statements. They do not activate for changes in views, nor by changes to tables made by APIs that do not transmit SQL statements to the MySQL Server

==> See below the last edit, things are moving on this domain

Triggers are not activated by foreign key actions.

And I do not think this will get fixed one day. Foreign key constraints are managed by the InnoDb storage and Triggers are managed by the MySQL SQL engine. Both are separated. Innodb is the only storage with constraint management, maybe they'll add triggers directly in the storage engine one day, maybe not.

But I have my own opinion on which element you should choose between the poor trigger implementation and the very useful foreign keys constraints support. And once you'll get used to database consistency you'll love PostgreSQL.

12/2017-Updating this Edit about MySQL:

as stated by @IstiaqueAhmed in the comments, the situation has changed on this subject. So follow the link and check the real up-to-date situation (which may change again in the future).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文