web-dev-qa-db-fra.com

PostgreSQL: FOREIGN KEY / ON DELETE CASCADE

J'ai deux tableaux comme ici:

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

Donc, la logique est simple, après que l'utilisateur a supprimé tous les livres de la catégorie x, x a été supprimé des chats, j'ai essayé la méthode ci-dessus mais ne fonctionne pas, après avoir nettoyé le livre de la table, la catégorie de la table est toujours remplie, qu'est-ce qui ne va pas?

25
juk

Une clé étrangère avec une suppression en cascade signifie que si un enregistrement de la table parent est supprimé, les enregistrements correspondants de la table enfant seront automatiquement supprimés. Cela s'appelle une suppression en cascade.

Vous dites d'une manière opposée, ce n'est pas que lorsque vous supprimez de la table enfant, les enregistrements seront supprimés de la table parent.

UPDATE 1:

L'option ON DELETE CASCADE permet de spécifier si vous souhaitez que les lignes soient supprimées dans une table enfant lorsque les lignes correspondantes sont supprimées dans la table parent. Si vous ne spécifiez pas de suppressions en cascade, le comportement par défaut du serveur de base de données vous empêche de supprimer des données dans une table si d'autres tables y font référence.

Si vous spécifiez cette option, plus tard lorsque vous supprimez une ligne de la table parent, le serveur de base de données supprime également toutes les lignes associées à cette ligne (clés étrangères) dans une table enfant. Le principal avantage de la fonctionnalité de suppression en cascade est qu'elle vous permet de réduire la quantité d'instructions SQL dont vous avez besoin pour effectuer des actions de suppression.

Donc, tout dépend de ce qui se passera lorsque vous supprimez des lignes de la table parent et non de la table enfant.

Ainsi, dans votre cas, lorsque l'utilisateur supprime des entrées de la table CAT, les lignes sont supprimées de la table livres. :)

J'espère que cela vous aide :)

66
Mari

Extrait de PostgreSQL documentation :

Les suppressions restreintes et en cascade sont les deux options les plus courantes. [...] CASCADE spécifie que lorsqu'une ligne référencée est supprimée, la ou les lignes qui la référencent doivent également être supprimées automatiquement.

Cela signifie que si vous supprimez une catégorie - référencée par des livres - le livre de référence sera également supprimé par ON DELETE CASCADE.

Exemple :

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 les clans CASCADE aux hobbits par 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)

Si vous avez vraiment besoin du contraire (vérifié par la base de données), vous devrez écrire un déclencheur!

21
Martin

Dans mon humble expérience avec postgres 9.6, la suppression en cascade ne fonctionne pas dans la pratique pour les tables qui dépassent une taille triviale.

  • Pire encore, pendant la cascade de suppression, les tables impliquées sont verrouillées de sorte que ces tables (et potentiellement toute votre base de données) sont inutilisables.
  • Pire encore, il est difficile d'obtenir des postgres pour vous dire ce qu'il fait pendant la cascade de suppression. Si cela prend du temps, quelle table ou tables la ralentit? C'est peut-être quelque part dans les informations pg_stats? C'est difficile à dire.
1
Gordon Vidaver