代码之家  ›  专栏  ›  技术社区  ›  meleyal

Postgres外键“on update”和“on delete”选项如何工作?

  •  21
  • meleyal  · 技术社区  · 16 年前

    任何人都能清楚地解释/举例说明这些功能的作用,以及何时使用它们是合适的吗?

    4 回复  |  直到 16 年前
        1
  •  25
  •   Community CDub    8 年前

    直接从 the manual

    我们知道,外键不允许创建与任何产品无关的订单。但是,如果在创建引用某个产品的订单后删除该产品呢?SQL也允许您处理这个问题。直观地说,我们有几个选择:

    不允许删除引用的产品

    同时删除订单

    还有别的吗?

    CREATE TABLE order_items (
     product_no integer REFERENCES products ON DELETE RESTRICT,
     order_id integer REFERENCES orders ON DELETE CASCADE,
     quantity integer,
     PRIMARY KEY (product_no, order_id)
    );
    

    限制和级联删除是两个最常见的选项。限制阻止删除引用的行。没有操作意味着,如果在选中约束时仍存在任何引用行,则会引发错误;如果不指定任何内容,则这是默认行为。(这两个选项之间的本质区别在于,任何操作都不允许将检查推迟到事务的后面,而restrict则不允许。)cascade指定当删除引用的行时,也应自动删除引用该行的行。还有两个其他选项:设置空值和设置默认值。这会导致在删除被引用行时,引用列分别设置为空值或默认值。请注意,这些并不能成为您遵守任何约束的借口。例如,如果某个操作指定了set default,但默认值不满足外键,则该操作将失败。

    与“删除”类似,也有“更新”功能,当引用的列发生更改(更新)时会调用该功能。可能的操作是相同的。

    编辑: 您可能想看看这个相关的问题: When/Why to use Cascading in SQL Server? . 问题/答案背后的概念是相同的。

        2
  •  0
  •   Patrick Desjardins    16 年前

    我有一个PostgreSQL数据库,当我有一个从数据库中删除的用户,我需要从另一个表中删除它的信息时,我使用on delete。这样,我只需要执行1个删除操作,而fk在删除时将从其他表中删除信息。

    更新时也可以这样做。如果更新表,并且字段具有“更新时使用”的FK,则如果在FK上进行了更改,则会在FK表上注意到您。

        3
  •  0
  •   Mark Brady    16 年前

    道克说的是真的…这可能相当方便。另一方面,让事情在数据库中自动发生可能是一个真正的问题,尤其是在消除数据方面。将来有人可能会指望FK通常会在有孩子的情况下阻止删除父表,并且没有意识到使用on-delete cascade不仅不能阻止删除,而且由于级联删除的瀑布效应,它会使数十个其他表中的大量数据消失。

    @亚瑟的评论。

    数据库中发生“隐藏”事件的频率越高,任何人对所发生的事情掌握得越少。触发器(这本质上是一个触发器)可以导致我删除一行的简单操作在整个数据库中产生广泛的结果。我发出一条DELETE语句,17个表受触发器和约束级联的影响,而这对命令的发出者来说都不是显而易见的。哦,如果我把删除父对象及其所有子对象的操作放在一个过程中,那么任何人都可以很容易和清楚地看到当我发出命令时会发生什么。

    这与我如何设计数据库毫无关系。它与触发器引入的操作问题有关。

        4
  •  0
  •   Jeff Edwards    15 年前

    您可以简单地编写一条警告消息,而不是编写方法来完成级联删除或级联更新的所有工作。比重新设计控制盘要容易得多,而且它使客户机(以及新开发人员)明白了这一点。