如何为postgres编写DELETE CASCADE?

时间:2010-09-14 17:59:48

标签: sql postgresql

我正在为postgres手动构建DELETE CASCADE语句。

我有一个'交易'和'切片'表,相关如下所示:

    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)

假设我要删除名称为“my_slice”的切片引用的所有事务和classification_items。我需要写什么?

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

5 个答案:

答案 0 :(得分:48)

Postgres外键支持CASCADE删除:

slice_id integer REFERENCES slice(id) ON DELETE CASCADE

答案 1 :(得分:13)

如果你不能做别人的建议:

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 :(得分:8)

这是在表中定义的东西,而不是DELETE查询。示例(查看订单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)
);

答案 3 :(得分:7)

您应该使用CASCADE删除,即使您继承了数据库架构,也应该这样做。您只需修改约束以将CASCADE删除添加到模式:

  1. 删除并重新创建约束以添加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. 现在,以下查询不仅会删除表my_slice中的slice记录,还会删除引用它的表transactionclassification_item中的所有记录:< / p>

    DELETE FROM slice WHERE name='my_slice';
    
  3. 即使原始模式由像SQLAlchemy这样的对象关系映射器创建,该过程也会起作用。但是,在这种情况下,每当架构更改或重新创建时,请务必重新应用该“补丁”。只有当它不能自动实现时,它毕竟不是一个好主意......

答案 4 :(得分:0)

可以通过设置约束属性&#39; On delete&#39;将其委托给DBMS。 = CASCADE。请参阅an example