更新不使用with子句

时间:2017-12-30 14:15:21

标签: sql postgresql common-table-expression insert-update postgresql-9.6

WITH first_insert AS 
(
    INSERT INTO first_insert_table (column_of_first_insert_table) 
    VALUES (10) 
    RETURNING first_insert_table_id
),
second_insert AS 
(
    INSERT INTO second_insert_table(column_of_second_insert_table)
    VALUES((SELECT * FROM first_insert)) 
    RETURNING second_insert_table_id
)  
--here doesn't update column_of_first_insert_table!
UPDATE first_insert_table 
SET column_of_first_insert_table = column_of_first_insert_table + 1
WHERE first_insert_table_id = (SELECT * FROM first_insert) ;

当我尝试更新column_of_first_insert_table表时,为什么此查询不会更新first_insert_table first_insert_table列?

1 个答案:

答案 0 :(得分:4)

它不执行预期更新的原因与您的示例的简化版本不会显示WITH子句中插入的行的原因相同:

with cte as (
  insert into first_insert_table (column_of_first_insert_table)
  values (10)
)
select * from first_insert_table

执行上述语句时,INSERT确实成功发生,但语句的SELECT部分不会,因为仅SELECT看到语句开始执行时存在的数据。

您的示例中也发生了同样的情况。 WHERE的{​​{1}}子句只能查找整个语句开始时存在的行,因此它不会看到UPDATE子句中插入的行。

记录此行为(7.8.2. Data-Modifying Statements in WITH):

  

WITH中的子语句彼此同时并与主查询同时执行。因此,在WITH中使用数据修改语句时,指定更新实际发生的顺序是不可预测的。 所有语句都使用相同的快照执行(参见第13章),因此他们无法“看到”彼此对目标表的影响。这可以减轻不可预测性的影响行更新的实际顺序,意味着WITH数据是在不同RETURNING子语句和主查询之间传递更改的唯一方法。