PostgreSQL: внешний ключ / on удалить каскад

У меня есть две таблицы, как здесь:

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 удаляется из кошек, я попробовал метод выше, но не работает, после того, как я очистил книгу таблицы, категория таблицы все еще заполнена, что случилось?

4 ответов


внешний ключ с каскадным удалением означает, что если запись в родительской таблице удалена, то соответствующие записи в дочерней таблице будут автоматически удалены. Это называется каскадным удалением.

вы говорите наоборот, это не то, что при удалении из дочерней таблицы записи будут удалены из родительской таблицы.

UPDATE 1:

ON DELETE CASCADE опция должна указать, хотите ли вы удалить строки в дочерней таблице, когда соответствующий строки удаляются в родительской таблице. Если каскадные удаления не указаны, поведение сервера базы данных по умолчанию запрещает удаление данных в таблице, если другие таблицы ссылаются на нее.

Если вы укажете этот параметр, позже при удалении строки в родительской таблице сервер баз данных также удалит все строки, связанные с этой строкой (внешние ключи) в дочерней таблице. Основным преимуществом функции каскадного удаления является то, что она позволяет уменьшить количество Инструкции SQL, необходимые для выполнения действий удаления.

Итак, все дело в том, что произойдет, когда вы удалите строки из родительской таблицы, а не из дочерней таблицы.

поэтому в вашем случае, когда пользователь удаляет записи из таблицы CATs, строки будут удалены из таблицы books. :)

надеюсь, это поможет вам :)


Exerpt из 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
);

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 cascade delete не работает на практике для таблиц, которые растут выше тривиального размера.

  • еще хуже, в то время как каскад удаления продолжается, задействованные таблицы заблокированы, поэтому эти таблицы (и, возможно, вся ваша база данных) непригодный.
  • еще хуже, трудно заставить postgres сказать вам, что это происходит во время каскада удаления. Если это займет много времени ... , какой стол или таблицы делает его медленным? Возможно, это где-то в информация pg_stats? Трудно сказать.

удаление ключа ковки 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
);