35

I'm manually constructing a DELETE CASCADE statement for postgres.

I have a 'transaction' and a 'slice' table, related as shown below:

    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)

Say I want to delete all transactions and classification_items referenced by the slice whose name is 'my_slice'. What do I need to write?

=# delete from classification_item where transaction_id= #...? 
=# delete from transaction where slice_id= #...? 
=# delete from slice where name='my_slice';
1
  • 1
    Suggestion: Improve the code block describing table structure. (I tried to improve this with an edit, but they rejected it …) With an entity-relationship diagram, it would save a lot of time to understand the table structure. Otherwise, just use consistent formatting, shorten lines to column width, and use whitespace lines to structure the block. The last two lines ("Foreign-key constraints") are redundant to one of the "Referenced by" sections. And in the intro you mention you have two tables, but you have three. Commented Dec 12, 2016 at 2:51

5 Answers 5

54

Postgres foreign keys support the CASCADE deletes:

slice_id integer REFERENCES slice(id) ON DELETE CASCADE

etc

Sign up to request clarification or add additional context in comments.

1 Comment

In other words, you dont write it, you just describe the relations and let Postgre handle the deletion.
20

In case you can't do what others have suggested:

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;

2 Comments

I can't; I've inherited fairly complex code that uses SQLAlchemy. This is ideal, thank you.
sqlalchemy supports on delete cascade: docs.sqlalchemy.org/en/latest/orm/cascades.html -- it's not this postgres directive exactly, but it's similar and might be better than doing this by hand
14

You should use CASCADE deletes, and it should be possible to do so even if you inherited a database schema. You would just modify the constraints to add the CASCADE deletes to the schemas:

  1. Drop and re-create the constraints to add CASCADE deletes:

    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. Now the following query will delete not just the my_slice record from table slice, but also all records from tablestransaction and classification_item referencing it:

    DELETE FROM slice WHERE name='my_slice';
    

That procedure will work even if the original schema is created by an object-relational mapper like SQLAlchemy. However in such a case, take care to re-apply that "patch" whenever the schema changes or is re-created. Only if that can't be implemented automatically, it might not be a good idea after all …

Comments

8

It's soemthing that is defined in the table rather than the DELETE Query. Example (look at 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)
);

Comments

1

It can be delegated to DBMS by set a constraint property 'On delete' = CASCADE. Please see an example.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.