PostgreSQL:删除子查询返回的行

sed*_*deh 1 sql postgresql subquery sql-delete

的基本语法DELETE

DELETE FROM table
WHERE condition
Run Code Online (Sandbox Code Playgroud)

是否有一种直接的方法可以在DELETE语句中使用子查询/别名,如下所示?

DELETE FROM (subquery) as sub
WHERE condition
Run Code Online (Sandbox Code Playgroud)

下面是一个最小的工作表,我尝试使用子查询/别名失败:

---create table
create table orderT (
    id integer PRIMARY KEY,
    country_code   varchar(2),
    created_date date,
    closed_date date);

---populate table
INSERT INTO orderT VALUES (1, 'US', now(), now() + interval '1 day' * 21);
INSERT INTO orderT VALUES (2, 'CA', now(), now() + interval '1 day' * 35);

--This does not work    
    DELETE
    FROM
      (SELECT *
       FROM orderT) AS sub
    WHERE sub.id = 1;
Run Code Online (Sandbox Code Playgroud)

你可以试试这里的代码。

PostgreSQL 9.5

Pat*_*ick 5

不,您不能直接执行此操作。原因是子查询可以从多个行源构建,包括表、视图、VALUES子句、其他子查询(由...构建)、集合返回函数,...可以想象规划器可以跟踪所有表中所有受影响的行,但它根本没有实现,太复杂了。

但是,您可以构造从表中删除包含在子查询中的所有行的序列,如下所示:

WITH complex_sub_query AS (
    SELECT Aid, Bid, Cid, many_more_columns
    FROM tableA
    JOIN tableB ON ...
    JOIN tableC ON ...
    ...
    WHERE complex_condition
), first_delete AS (
    DELETE FROM tableC WHERE id IN (SELECT Cid FROM complex_sub_query)
), second_delete AS (
    DELETE FROM tableB WHERE id IN (SELECT Bid FROM complex_sub_query)
)
DELETE FROM tableA WHERE id IN (SELECT Aid FROM complex_sub_query);
Run Code Online (Sandbox Code Playgroud)

complex_sub_query物化如此行,包你想从删除的表的主键,可向下列的DELETE语句。由于删除的顺序通常与外键、其他约束和级联删除相关,因此您必须仔细分析数据模型以按正确的顺序执行操作。