Postgresql PG使用CTE和DML语句的意外行为

Postgresql PG使用CTE和DML语句的意外行为,postgresql,Postgresql,我偶然发现了这一点,为了使问题易于解释,我在下面放了一个示例代码 表格: CREATE TABLE "MyTab" ( "Id" integer NOT NULL DEFAULT nextval('"Anukram"."MyTab_Id_seq"'::regclass), "Text1" text COLLATE pg_catalog."default" NOT

我偶然发现了这一点,为了使问题易于解释,我在下面放了一个示例代码

表格:

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".*
数据填充:

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".*
相关声明:

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".*
带有“Temp”作为(
更新“MyTab”
设置“Text2”=“Text2”| |“Text2”
其中“Text1”='L'
返回*
)
删除
来自“MyTab”

使用“Temp”---在这种情况下的具体结果令人惊讶,但潜在的问题是:

不支持在一条语句中尝试更新同一行两次。只有一个修改发生,但要可靠地预测是哪一个修改并不容易(有时也不可能)。这也适用于删除已在同一语句中更新的行:仅执行更新。因此,通常应避免在一条语句中两次修改一行尤其要避免使用可能影响主语句或同级子语句更改的相同行的子语句编写
。这种说法的效果是无法预测的。

(我的重点。)


简而言之:不要试图
更新
删除同一语句中的同一行,否则可能会发生奇怪的事情。

@LaurenzAlbe虽然仍然很奇怪,但这仍然不能解释为什么在使用所有内容按预期进行注释后(所有内容仍然是一个语句)…我无法确切解释原因(必须使用调试器),但它可能会影响执行顺序,因此“不可预测”以其他方式解决。