INSERT 中不明确的列引用 ... ON CONFLICT DO UPDATE

Ambiguous column reference in INSERT ... ON CONFLICT DO UPDATE

给定一个 table:

CREATE TABLE IF NOT EXISTS test."TestCounter" 
("id" TEXT PRIMARY KEY, 
 "count" INTEGER);

如果记录已经存在,我想插入一条记录并增加计数器

INSERT INTO test."TestCounter" ("id")
VALUES ('id-0')
 ON CONFLICT ("id") DO UPDATE
 SET "count" = ("count" + 1)
 RETURNING "count"

目前我收到这个错误:

ERROR:  column reference "count" is ambiguous
LINE 4:  SET "count" = "count" + 1
                       ^
SQL state: 42702
Character: 107

您需要 table 限定列,否则会产生歧义。
使用虚拟 table 名称 excluded 来引用输入行。但是您可能想引用目标列,所以用目标的名称限定 table:

INSERT INTO test.test_counter (id)
VALUES ('id-0')
ON CONFLICT (id) DO UPDATE
SET count = test_counter.count + 1  -- here
RETURNING count;

The manual:

Note that the special excluded table is used to reference values originally proposed for insertion.

来自虚拟输入 table excluded 的单行包含目标 table 的 所有 列,即使未在INSERTVALUES 表达式的目标列列表。所以你遇到的歧义总是存在的,不管count是不是明确针对

旁白:目标列列表中省略的列默认为其各自的列 DEFAULT 值,默认为 NULLNULL 是默认列 DEFAULT ).也就是说,在您的设置中它将默认为 NULL,在我下面改进的设置中默认为 1。并应用行级触发器 BEFORE INSERT(如果有)。

但这两者都不适用于示例,因为它毕竟指的是 target 列。

值得注意的是,列名 count 的其他两个实例是明确的(因此不需要 table 限定),因为它们只能引用 目标 table.

当列 count 未定义 NOT NULL 时,您的设置很容易中断,因为 NULL + 1 仍然是 NULL。这种设置会更有意义:

CREATE TABLE test.test_counter (
  id    text PRIMARY KEY
, count integer NOT NULL DEFAULT 1
);

在我的示例中也没有使用引用的 CaMeL 大小写名称。参见:

  • Are PostgreSQL column names case-sensitive?