patternsqlMajor
Why can't rows inserted in a CTE be updated in the same statement?
Viewed 0 times
rowswhycanthesamestatementcteinsertedupdated
Problem
In PostgreSQL 9.5, given a simple table created with:
I run SQL to INSERT a value, then UPDATE it in the same statement:
The result is that the UPDATE is ignored:
Why is this? Is this limitation part of the SQL standard (i.e. present in other databases), or something specific to PostgreSQL that might be fixed in future? The WITH queries documentation says multiple UPDATEs are not supported, but does not mention INSERTs and UPDATEs.
create table tbl (
id serial primary key,
val integer
);I run SQL to INSERT a value, then UPDATE it in the same statement:
WITH newval AS (
INSERT INTO tbl(val) VALUES (1) RETURNING id
) UPDATE tbl SET val=2 FROM newval WHERE tbl.id=newval.id;The result is that the UPDATE is ignored:
testdb=> select * from tbl;
┌────┬─────┐
│ id │ val │
├────┼─────┤
│ 1 │ 1 │
└────┴─────┘Why is this? Is this limitation part of the SQL standard (i.e. present in other databases), or something specific to PostgreSQL that might be fixed in future? The WITH queries documentation says multiple UPDATEs are not supported, but does not mention INSERTs and UPDATEs.
Solution
All sub-statements of a query with CTEs happen virtually at the same time. I.e., they are based on the same snapshot of the database.
The
All the statements are executed with the same snapshot (see Chapter 13), so they cannot "see" one another's effects on the target tables.
Each statement can see what's returned by another CTE in the
You would need two statements (in a single transaction) for what you are trying to do. The given example should really just be a single
The
UPDATE sees the same state of the underlying table as the INSERT, which means the row with val = 1 is not there, yet. The manual clarifies here:All the statements are executed with the same snapshot (see Chapter 13), so they cannot "see" one another's effects on the target tables.
Each statement can see what's returned by another CTE in the
RETURNING clause. But the underlying tables look all the same to them.You would need two statements (in a single transaction) for what you are trying to do. The given example should really just be a single
INSERT to begin with, but that may be due to the simplified example.Context
StackExchange Database Administrators Q#151199, answer score: 27
Revisions (0)
No revisions yet.