我偶然发现了这一点,为了使问题易于解释,我在下面放置了示例代码
表:
CREATE TABLE "MyTab"
(
"Id" integer NOT NULL DEFAULT nextval('"Anukram"."MyTab_Id_seq"'::regclass),
"Text1" text COLLATE pg_catalog."default" NOT NULL,
"Text2" text COLLATE pg_catalog."default" NOT NULL,
CONSTRAINT "MyTab_pkey" PRIMARY KEY ("Id")
)
数据填写:
INSERT INTO "Anukram"."MyTab" ("Text1","Text2") values
('L','R'),('A','B'),('C','D'), ('L','R1'),('A','B1'),('C','D1')
有问题的陈述:
WITH "Temp" AS (
UPDATE "MyTab"
SET "Text2"="Text2" || "Text2"
WHERE "Text1"='L'
RETURNING *
)
DELETE
FROM "MyTab"
USING "Temp"-- <--This is used in some more conditions in where clause not shown here
WHERE "MyTab"."Text1"='L'
RETURNING "MyTab".*
期望:
它应该删除“Text1”列中带有“L”的 2 行
实际:
它只删除一行(查看 RETURNING 语句)
观察:
如果我删除Using子句,一切都会按预期运行
那么我在这里缺少什么?或者这是 PG 使用的快照中的错误?
最佳答案
本例的具体结果令人惊讶,但根本问题is documented :
Trying to update the same row twice in a single statement is not supported. Only one of the modifications takes place, but it is not easy (and sometimes not possible) to reliably predict which one. This also applies to deleting a row that was already updated in the same statement: only the update is performed. Therefore you should generally avoid trying to modify a single row twice in a single statement. In particular avoid writing
WITH
sub-statements that could affect the same rows changed by the main statement or a sibling sub-statement. The effects of such a statement will not be predictable.
(强调我的。)
简而言之:不要尝试在同一语句中UPDATE
和DELETE
同一行,否则可能会发生奇怪的事情。
关于postgresql - PG 使用 CTE 和 DML 语句的意外行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64817085/