繁体   English   中英

PostgreSQL:外键/删除级联

[英]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 从猫中删除,我尝试了上面的方法但不起作用,在我清理表书后,表类别仍然填充,这是怎么回事?

级联删除的外键意味着如果父表中的一条记录被删除,那么子表中对应的记录将被自动删除。 这称为级联删除。

您以相反的方式说,这并不是说当您从子表中删除时,记录将从父表中删除。

UPDATE 1:

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

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

因此,这就是当您从父表而不是子表中删除行时会发生什么。

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

希望这可以帮助你:)

PostgreSQL 文档摘录

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

这意味着如果您删除schemas.books中由schemas.category中的category_id引用的行,任何此类引用行也将被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 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)

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

根据我对 postgres 9.6 的简陋经验,级联删除在实践中对于增长超过微不足道大小的表不起作用。

  • 更糟糕的是,当删除级联进行时,所涉及的表被锁定,因此这些表(可能还有您的整个数据库)无法使用。
  • 更糟糕的是,很难让 postgres 告诉你它在删除级联期间做了什么。 如果需要很长时间,哪个或哪些表使它变慢? 也许它在 pg_stats 信息中的某个地方? 很难说。

PostgreSQL Forging Key DELETE, UPDATE CASCADE

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
);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM