PostgreSQL: FOREIGN KEY/ON DELETE 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)
);

所以逻辑很简单,当用户删除了类别 x 下的所有图书,x 从 cat 中删除,我尝试了上面的方法,但是没有工作,当我清除了表的书,表的类别仍然填充,怎么了?

169068 次浏览

具有级联删除的外键意味着,如果父表中的一条记录被删除,那么子表中相应的记录将被自动删除。这叫做级联删除。

你是说相反的方式,这并不是说当你从子表中删除时,记录就会从父表中删除。

UPDATE 1:

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

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

因此,这完全是关于从 Parent 表中删除行而不是从子表中删除行时会发生什么。

因此,在您的情况下,当用户从 categories表中删除条目时,将从 books 表中删除行。 :)

希望这个能帮到你:)

摘自 PostgreSQL 文件:

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

这意味着如果在 schemas.category中删除 category_idschemas.books中引用的一行,那么任何这样的引用行也将被 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
);

DELETE FROM部族将 CASCADEREFERENCES霍比特人。

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)

如果您真的需要相反的东西(由数据库检查) ,那么您必须编写一个触发器!

锻造关键字删除,更新级联

CREATE TABLE apps_user(
user_id SERIAL PRIMARY KEY,
username character varying(30),
userpass character varying(50),
created_on DATE
);


CREATE TABLE apps_profile(
pro_id SERIAL PRIMARY KEY,
user_id INT4 REFERENCES apps_user(user_id) ON DELETE CASCADE ON UPDATE CASCADE,
firstname VARCHAR(30),
lastname VARCHAR(50),
email VARCHAR UNIQUE,
dob DATE
);

根据我在 postgres 9.6中的经验,级联删除在实践中不适用于那些大小超过平常值的表。

  • 更糟糕的是,当删除级联正在进行的时候,涉及到了表 锁定,这样这些表(以及可能的整个数据库)就可以 无法使用。
  • 更糟的是,很难让 Postgres 告诉你 如果需要很长时间, 是哪张桌子让它变慢了? 也许是在 Pg _ stats 信息? 很难说。