代码之家  ›  专栏  ›  技术社区  ›  Sadeq Dousti

相当于“嵌套删除”的执行性能SQL查询

  •  0
  • Sadeq Dousti  · 技术社区  · 2 年前

    考虑以下ERD Order , Item Article 实体:

    ERD for Order, Item and Article entities

    我想删除 Orders 满足a 复杂条件 ,然后删除 Items 与这些 订单 ,最后删除 Articles 与这些 项目 .

    级联删除自 订单 项目 可能是 顺序 是的父级 项目 . 但级联从中删除 项目 文章 不可能 项目 不是的父级 文章 . 设置触发器也不是一个选项,因为通常我不想删除 文章 每当 项目 已删除-它只应在该查询的上下文中发生。

    我正在使用PostgreSQL,它支持 DELETE ... RETURNING 声明。不幸的是,结果 不能 嵌套方式如下:

    DELETE FROM articles WHERE id IN
      (DELETE FROM items WHERE order_id IN
        (DELETE FROM orders WHERE complex_condition RETURNING id)
      RETURNING article_id)
    

    执行这三条delete语句最有效的方法是什么?每个表包含数千万条记录 complex_condition 是最耗时的部分,所以我不希望执行多次。

    我的一个想法是创建这样一个临时表:

    CREATE TEMP TABLE id_of_order_to_be_deleted
    AS
    WITH cte1 AS (SELECT id FROM orders WHERE complex_condition)
    SELECT *
    FROM cte1;
    

    然后使用它删除 订单 项目 . 这边 复杂的\u条件 仅评估一次。但我认为这是一种过分的做法,应该有一个更简单的解决方案。

    1 回复  |  直到 2 年前
        1
  •  2
  •   a_horse_with_no_name    2 年前

    结果 可以 使用数据修改CTE进行嵌套:

    with deleted_orders as (
      DELETE FROM orders 
      WHERE complex_condition 
      RETURNING id
    ), deleted_items as (
      DELETE FROM items 
      WHERE order_id IN (select id from deleted_orders)
      returning article_id
    )
    DELETE FROM articles 
    WHERE id IN (select article_id from deleted_items);
    

    你可能想试试 where exists 条件作为替代-有时比 IN 条件