为什么我看不到CTE中所做的更改?

时间:2019-12-24 16:15:12

标签: sql postgresql common-table-expression

create table tab(id int);

insert into tab(id) values(1);

with x as (delete from tab where id = 1 returning id),
y as (select * from tab where id in (select id from x))
select * from y;

-- outputs a row with "1"
-- i need no rows returned

为什么我仍在y CTE子查询中看到已删除的行? xy节应按顺序执行,因为y取决于x。您能否向我解释为什么我看不到x的更改?我该怎么做才能看到他们?

我不确定这与隔离级别有关,因为所有操作都在同一查询=>同一事务中完成

谢谢!

1 个答案:

答案 0 :(得分:1)

该行为记录在"7.8.2. Data-Modifying Statements in WITH"中:

  

(...)

     

WITH中的子语句与每个子语句同时执行   其他和主要查询。因此,在使用数据修改时   WITH中的语句,指定的更新顺序   实际发生是无法预料的。所有语句都用   相同的快照(请参见Chapter 13),因此它们   无法“看到”对方对目标表的影响。 (...)

     

(...)

要从表中删除并在一个查询中获得表的模式为空的结果,只需在CTE中删除并使用错误的WHERE子句从表中进行选择。

WITH
cte
AS
(
DELETE FROM tab
       WHERE id = 1 
)
SELECT *
       FROM tab
       WHERE false;