PostgreSQL:外键/删除级联

PostgreSQL:外键/删除级联,sql,postgresql,cascade,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,

我有两张这样的桌子:

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中删除,我尝试了上面的方法,但不起作用,在我清理了table book之后,table category仍然填充,怎么了?

带有级联删除的外键意味着如果父表中的记录被删除,然后子表中相应的记录将自动删除。这称为级联删除

您的意思正好相反,这并不是说当您从子表中删除记录时,记录将从父表中删除

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

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

所以这一切都是关于从父表而不是子表中删除行时会发生什么。

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


希望这对您有所帮助:)

摘自PostgreSQL:

限制和级联删除是两种最常见的选项。[…]
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
部族将通过
参考资料
级联
给霍比特人

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)
如果您真的需要相反的方法(由数据库检查),则必须编写触发器

PostgreSQL密钥删除、更新级联


根据我在postgres 9.6中的拙劣经验,cascade delete在实践中不适用于超过小规模的表

  • 更糟糕的是,在进行删除级联时,所涉及的表 已锁定,因此这些表(以及可能的整个数据库)是 无法使用
  • 更糟糕的是,很难让博士后告诉你什么 它在删除级联期间执行。如果需要很长时间, 哪张桌子慢了?也许它就在你家的某个地方 pg_统计信息?很难说

是,请参见SQL中没有树结构。你真的应该试着用引用来重写这个答案,而不是“父”或“子”。postgres的OO继承方面有父表,但这也是答案应该避免使用父/子术语并描述引用的更多原因。我确信@Mari理解CASCADE指定的内容,但就术语而言,这是一个不正确的答案。如上所述,在继承表中,当从父表中删除(相同)行时,总是会删除子表。作为旁注,我想服务器的默认行为是特定于实际服务器的。在Postgres中,默认行为是RESTRICT。它可能是不正确的术语(你们都没有提供更好的替代方法),但它有助于理解术语的含义是不明确的。层次结构的父类和子类都可能包含FK约束,因此该术语无助于理解哪个删除导致了另一个删除。最好将它们称为“定义约束的表”(或关系的“所有者”)和“引用的表”。这种剪切粘贴是一个与问题无关的糟糕示例,最重要的关键字被替换为听起来相同的随机关键字。公平地说,“伪造”有点泄露了它。这是工作的定义,在一个具有适当事务的数据库中工作。其次,这并不是问题的答案。这一解释最终让我理解了引用/级联语法的实际含义,非常感谢!
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
);