postgresql - CTE 和 DML 语句的 PG 意外行为
问题描述
我偶然发现了这一点,为了让问题易于解释,我在下面放了一个示例代码
桌子:
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”列中删除 2 行带有“L”的行
实际:
它只删除一行(查看 RETURNING 语句)
观察:
如果我删除 Using 子句,一切都会按预期运行
那么我在这里缺少什么?或者这是PG使用的快照中的错误?
解决方案
这种情况下的具体结果令人惊讶,但根本问题已记录在案:
不支持在单个语句中尝试两次更新同一行。只进行了一项修改,但要可靠地预测哪一项并不容易(有时也不可能)。这也适用于删除已在同一语句中更新的行:仅执行更新。因此,您通常应避免尝试在单个语句中两次修改单个行。特别是避免编写
WITH
可能影响由主语句或兄弟子语句更改的相同行的子语句。这种声明的影响是不可预测的。
(强调我的。)
简而言之:不要试图UPDATE
和DELETE
同一行在同一个语句中,否则可能会发生奇怪的事情。
推荐阅读
- html - 有没有办法使用 ` ` 和 github 页面来实现正确的链接?
- html - 获取一条垂直线以向下运行页面
- formatting - 放置分节符时如何修复图形标题自动编号?
- java - 代码有效,但从文件中出现奇怪的错误,我不允许更改
- docker - 如何在 docker-compose 中运行同一构建的多个版本?
- java - 如何国际化 Spring Boot 中的 API 错误?
- javascript - 如何使用 jquery 排除数组中的空值和键?
- laravel - 如何在满足计数条件的情况下查询具有多对多关系的表
- javascript - 如何修复 React-Native 中未处理的 JS 异常和 AppRegistry 问题
- apache-spark - Spark 将数据帧直接从 Hive 写入本地文件系统