web-dev-qa-db-fra.com

Comment écrit-on un DELETE CASCADE pour postgres?

Je construis manuellement une instruction DELETE CASCADE pour postgres.

J'ai une table 'transaction' et une table 'slice', comme illustré ci-dessous:

    Table "public.slice"
  Column  | Type | Modifiers 
----------+------+-----------
 id       | text | not null
 name     | text | 
Referenced by:
    TABLE "transaction" CONSTRAINT "transaction_slice_id_fkey" FOREIGN KEY (slice_id) REFERENCES slice(id)
 Table "public.transaction"
  Column  | Type | Modifiers 
----------+------+-----------
 id       | text | not null
 slice_id | text | 
Referenced by:
    TABLE "classification_item" CONSTRAINT "classification_item_transaction_id_fkey" FOREIGN KEY (transaction_id) REFERENCES transaction(id)
Table "public.classification_item"
     Column     | Type | Modifiers 
----------------+------+-----------
 id             | text | not null
 transaction_id | text | 
Foreign-key constraints:
    "classification_item_transaction_id_fkey" FOREIGN KEY (transaction_id) REFERENCES transaction(id)

Dites que je veux supprimer toutes les transactions et tous les éléments de classification référencés par la tranche dont le nom est "my_slice". De quoi ai-je besoin pour écrire?

=# delete from classification_item where transaction_id= #...? 
=# delete from transaction where slice_id= #...? 
=# delete from slice where name='my_slice';
26
AP257

Si vous ne pouvez pas faire ce que d’autres ont suggéré:

begin;
delete from classification_item where transaction_id in (select id from "transaction" where slice_id = (select id from slice where name = 'my_slice'));
delete from "transaction" where slice_id in (select id from slice where name='my_slice');
delete from slice where name='my_slice';
commit;
13
Milen A. Radev

Les clés étrangères Postgres prennent en charge les suppressions CASCADE:

slice_id integer REFERENCES slice(id) ON DELETE CASCADE

etc

47
jira

C'est quelque chose qui est défini dans la table plutôt que la requête DELETE. Exemple (regardez order_id):

CREATE TABLE order_items (
    product_no integer REFERENCES products ON DELETE RESTRICT,
    order_id integer REFERENCES orders ON DELETE CASCADE,
    quantity integer,
    PRIMARY KEY (product_no, order_id)
);
8
Abe Miessler

Vous devez utiliser les suppressions CASCADE et il devrait être possible de le faire même si vous avez hérité d'un schéma de base de données. Il vous suffirait de modifier les contraintes pour ajouter les suppressions CASCADE aux schémas:

  1. Supprimez et recréez les contraintes pour ajouter des suppressions CASCADE:

    ALTER TABLE ONLY "transaction" 
        DROP CONSTRAINT transaction_slice_id_fkey;
    ALTER TABLE ONLY "transaction" 
        ADD CONSTRAINT transaction_slice_id_fkey 
        FOREIGN KEY (slice_id) REFERENCES slice(id) ON DELETE CASCADE;
    
    ALTER TABLE ONLY "classification_item" 
        DROP CONSTRAINT classification_item_transaction_id_fkey;
    ALTER TABLE ONLY "classification_item" 
        ADD CONSTRAINT classification_item_transaction_id_fkey 
        FOREIGN KEY (transaction_id) REFERENCES transaction(id) ON DELETE CASCADE;
    
  2. Désormais, la requête suivante supprimera non seulement l'enregistrement my_slice de la table slice, mais également tous les enregistrements des tablestransaction et classification_item qui le référence:

    DELETE FROM slice WHERE name='my_slice';
    

Cette procédure fonctionnera même si le schéma d'origine est créé par un mappeur relationnel-objet tel que SQLAlchemy. Cependant, dans un tel cas, veillez à réappliquer ce "correctif" chaque fois que le schéma change ou est recréé. Seulement si cela ne peut pas être implémenté automatiquement, cela pourrait ne pas être une bonne idée après tout…

7
tanius

Il peut être délégué au SGBD en définissant une propriété de contrainte 'On delete' = CASCADE. S'il vous plaît voir un exemple .

0
Oleg Tatarchuk