PostgreSQL:FOREIGN KEY/ON DELETE CASCADE

juk*_*juk 27 sql postgresql cascade

我有两张桌子在这里:

DROP   TABLE  IF EXISTS schemas.book;
DROP   TABLE  IF EXISTS schemas.category;
DROP   SCHEMA IF EXISTS schemas;
CREATE SCHEMA schemas;

CREATE TABLE schemas.category (
  id          BIGSERIAL PRIMARY KEY,
  name        VARCHAR   NOT NULL,
  UNIQUE(name)
);

CREATE TABLE schemas.book (
  id          BIGSERIAL PRIMARY KEY,
  published   DATE      NOT NULL,
  category_id BIGINT    NOT NULL REFERENCES schemas.category ON DELETE CASCADE ON UPDATE CASCADE,
  author      VARCHAR   NOT NULL,
  name        VARCHAR   NOT NULL,
  UNIQUE(published, author, name),
  FOREIGN KEY(category_id) REFERENCES schemas.category (id)
);
Run Code Online (Sandbox Code Playgroud)

所以逻辑很简单,用户删除了类别x下​​的所有书籍后,x从猫中删除,我尝试了上面的方法但是不起作用,在我清理了表格书之后,表格类别仍然填充,有什么问题?

Mar*_*ari 68

具有级联删除的外键意味着如果删除父表中的记录,则将自动删除子表中的相应记录.这称为级联删除.

你是以相反的方式说,这不是当你从子表中删除时,那么记录将从父表中删除.

UPDATE 1:
Run Code Online (Sandbox Code Playgroud)

ON DELETE CASCADE选项用于指定在父表中删除相应行时是否要在子表中删除行.如果未指定级联删除,则数据库服务器的默认行为会阻止您删除表中的数据(如果其他表引用它).

如果指定此选项,稍后在删除父表中的行时,数据库服务器还会删除子表中与该行(外键)关联的所有行.级联删除功能的主要优点是它允许您减少执行删除操作所需的SQL语句数量.

所以当你从父表中删除行而不是从子表中删除行时会发生什么.

因此,在用户从CAT表中删除条目的情况下,将从books表中删除行.:)

希望这可以帮助你:)

  • SQL中没有树结构.你应该真的尝试用引用来重写这个答案,而不是"父母"或"孩子". (11认同)
  • 术语含糊不清。层次结构的父类和子类都可能持有 FK 约束,因此该术语无助于理解哪个删除导致另一个删除。如果您将它们称为“定义约束的表”(或关系的“所有者”)和“引用的表”,那就更好了。 (5认同)
  • 这可能是不正确的术语(你们都没有提供更好的选择),但它有助于理解含义 (4认同)
  • postgres的OO继承方面有*父表,但这更应该是答案应避免使用父/子术语并描述*引用*. (3认同)
  • 我非常确信@Mari 理解 CASCADE 指定的内容,但就术语而言,这是一个不正确的答案。如上所述,在继承表中,当从父表中删除(相同)行时,子表总是被删除。作为旁注,我猜服务器的默认行为将特定于实际服务器。在 Postgres 中,默认行为是 RESTRICT。 (2认同)

Mar*_*tin 30

从PostgreSQL 文档中摘录:

限制和级联删除是两种最常见的选项.[...] CASCADE指定当删除引用的行时,也应自动删除引用它的行.

这意味着如果删除书籍引用的类别,也会删除引用书籍ON DELETE CASCADE.

示例:

CREATE SCHEMA shire;

CREATE TABLE shire.clans (
    id serial PRIMARY KEY,
    clan varchar
);

CREATE TABLE shire.hobbits (
    id serial PRIMARY KEY,
    hobbit varchar,
    clan_id integer REFERENCES shire.clans (id) ON DELETE CASCADE
);
Run Code Online (Sandbox Code Playgroud)

DELETE FROM部落将CASCADE通过霍比特人REFERENCES.

sauron@mordor> psql
sauron=# SELECT * FROM shire.clans;
 id |    clan    
----+------------
  1 | Baggins
  2 | Gamgi
(2 rows)

sauron=# SELECT * FROM shire.hobbits;
 id |  hobbit  | clan_id 
----+----------+---------
  1 | Bilbo    |       1
  2 | Frodo    |       1
  3 | Samwise  |       2
(3 rows)

sauron=# DELETE FROM shire.clans WHERE id = 1 RETURNING *;
 id |  clan   
----+---------
  1 | Baggins
(1 row)

DELETE 1
sauron=# SELECT * FROM shire.hobbits;
 id |  hobbit  | clan_id 
----+----------+---------
  3 | Samwise  |       2
(1 row)
Run Code Online (Sandbox Code Playgroud)

如果你真的需要相反的(由数据库检查),你将不得不写一个触发器!

  • 这是最终使我理解此REFERENCES / CASCADE语法实际含义的解释,非常感谢! (2认同)