PostgreSQL:外键/删除时级联

e7arh2l6  于 2022-12-26  发布在  PostgreSQL
关注(0)|答案(4)|浏览(602)

我有两张table像这样:

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从cats中删除,我尝试了上面的方法,但是不起作用,当我清理了表格图书,表格类别仍然填充,怎么了?

o2gm4chl

o2gm4chl1#

具有级联删除的外键意味着如果父表中的记录被删除,则子表中的相应记录也将被自动删除。这称为级联删除。
你的意思正好相反,这并不是说你从子表中删除的时候,父表中的记录也会被删除。

UPDATE 1:

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

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

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

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

w8rqjzmb

w8rqjzmb2#

限制删除和级联删除是两个最常用的选项。[...] CASCADE指定当删除引用的行时,引用它的行也应自动删除。
这意味着,如果您删除schemas.category中的一行,而schemas.books中的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)

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

z4iuyo4d

z4iuyo4d3#

在我使用postgres 9.6的经验中,级联删除在实际中对于超过微小大小的表不起作用。

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

gcuhipw94#

PostgreSQL伪造键删除、更新级联

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

相关问题