Sql 如何为postgres编写删除级联?

Sql 如何为postgres编写删除级联?,sql,postgresql,Sql,Postgresql,我正在为postgres手动构造一个DELETE CASCADE语句 我有一个“事务”和一个“切片”表,如下所示: Table "public.slice" Column | Type | Modifiers ----------+------+----------- id | text | not null name | text | Referenced by: TABLE "transaction" CONSTRAINT "transact

我正在为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)
假设我要删除名称为“我的切片”的切片引用的所有事务和分类项目。我需要写什么

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

Postgres外键支持级联删除:

slice_id integer REFERENCES slice(id) ON DELETE 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;

以防万一你不能按照别人的建议去做:

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;

表中定义的是soemthing,而不是DELETE查询。示例(查看订单id):


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

  • 删除并重新创建约束以添加级联删除:

    slice_id integer REFERENCES slice(id) ON DELETE 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;
    
  • 现在,下面的查询不仅将删除表
    切片
    中的
    my\u切片
    记录,还将删除引用它的表
    事务
    分类项目
    中的所有记录:

    DELETE FROM slice WHERE name='my_slice';
    

  • 即使原始模式是由对象关系映射器(如SQLAlchemy)创建的,该过程也可以工作。但是,在这种情况下,只要模式发生更改或被重新创建,就要注意重新应用该“补丁”。只有在无法自动实现的情况下,这才可能不是一个好主意……

    通过设置约束属性“On delete”=CASCADE,可以将其委托给DBMS。请看。

    换句话说,你不需要写,你只需要描述关系,让Postgre处理删除。我不能;我继承了使用SQLAlchemy的相当复杂的代码。这很理想,谢谢。sqlalchemy支持delete cascade:--它不是这个postgres指令,但它很类似,可能比手工操作要好:改进描述表结构的代码块。(我试图通过编辑来改进这一点,但他们拒绝了…)使用实体关系图,可以节省大量时间来理解表结构。否则,只需使用一致的格式,将行缩短到列宽,并使用空白行来构造块。最后两行(“外键约束”)对于其中一个“引用对象”部分是多余的。在介绍中你提到你有两张桌子,但你有三张。