【问题标题】:Ambiguous column reference in INSERT ... ON CONFLICT DO UPDATEINSERT ... ON CONFLICT DO UPDATE 中的不明确列引用
【发布时间】:2021-02-15 03:33:30
【问题描述】:

给定一张桌子:

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

【问题讨论】:

  • 尝试替换成
  • @BeshambherChaukhwan:Postgres(或标准 SQL)中没有“替换为”。
  • 哦,我的错。请检查这个答案stackoverflow.com/questions/11135501/…
  • @BeshambherChaukhwan:触发器也不能解决这个问题,也不需要,请参阅下面的答案。

标签: sql postgresql upsert


【解决方案1】:

您需要对列进行表格限定,否则会不明确。
使用虚拟表名称excluded 来引用输入行。但是您可能想要引用目标列,因此使用目标表的名称进行限定:

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:

请注意,特殊的excluded 表用于引用最初建议插入的值。

来自虚拟输入表excluded 的单行包含目标表的所有 列,即使没有列在INSERTVALUES 表达式的目标列列表中。因此,无论count 是否明确定位,您遇到的歧义始终存在。

另外:目标列列表中省略的列默认为其各自的列DEFAULT 值,默认为NULLNULL 为默认列DEFAULT)。即,在您的设置中默认为NULL,在下面我改进的设置中默认为1。并应用行级触发器BEFORE INSERT(如果有)。

但这都不适用于该示例,因为它毕竟引用了 target 列。

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

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

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

在我的示例中也没有使用带引号的 CaMeL 案例名称。见:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-08-02
    • 2021-02-16
    • 2023-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-11
    • 1970-01-01
    相关资源
    最近更新 更多