ON CONFLICT DO UPDATE 缺少 FROM 子句
ON CONFLICT DO UPDATE has missing FROM-clause
我有一个简单的 table(id 和名称列,都是唯一的),我正在导入一个制表符分隔的 CSV 文件。
我是 运行 psql 9.5,想尝试新的 ON CONFLICT
功能来在 ID 已经存在的情况下更新名称列。
CREATE TEMP TABLE tmp_x AS SELECT * FROM repos LIMIT 0;
COPY tmp_x FROM '/Users/George/git-parser/repo_file' (format csv, delimiter E'\t');
INSERT INTO repos SELECT * FROM tmp_x
ON CONFLICT(name) DO UPDATE SET name = tmp_x.name;
DROP TABLE tmp_x;
我收到这个错误:
SELECT 0
COPY 1
ERROR: missing FROM-clause entry for table "tmp_x"
LINE 4: ON CONFLICT(name) DO UPDATE SET name = tmp_x.name;
^
Query failed
PostgreSQL said: missing FROM-clause entry for table "tmp_x"
不太确定这里出了什么问题。
如果你看一下 the documentation of the ON CONFLICT
clause,它说的是 "conflict action":
The SET and WHERE clauses in ON CONFLICT DO UPDATE have access to the existing row using the table's name (or an alias)
在您的查询中,目标 table 是 repos
。
另一方面,tmp_x
是您要插入的数据的来源,但 ON CONFLICT
子句不能 "see" - 它正在查看特定的已计算但失败的行。想想你是否写过这样的东西:
INSERT INTO repos SELECT max(foo_id) FROM tmp_x
显然,无法插入 repos
的行访问 tmp_x
.
中的任何一行是没有意义的
如果无法查看被拒绝的数据,整个功能将毫无用处,但如果我们继续阅读:
... and to rows proposed for insertion using the special excluded table.
因此,您需要访问神奇的 table 别名 excluded
,其中包含您尝试插入但发生冲突的值,给您:
INSERT INTO repos SELECT * FROM tmp_x
ON CONFLICT(name) DO UPDATE SET name = excluded.name;
如果为此目的弹出一个假想的 table 名称看起来很奇怪,请考虑在编写触发器时发生类似的事情,您会得到 OLD
和 NEW
(取决于关于您正在编写的触发器类型)。
我有一个简单的 table(id 和名称列,都是唯一的),我正在导入一个制表符分隔的 CSV 文件。
我是 运行 psql 9.5,想尝试新的 ON CONFLICT
功能来在 ID 已经存在的情况下更新名称列。
CREATE TEMP TABLE tmp_x AS SELECT * FROM repos LIMIT 0;
COPY tmp_x FROM '/Users/George/git-parser/repo_file' (format csv, delimiter E'\t');
INSERT INTO repos SELECT * FROM tmp_x
ON CONFLICT(name) DO UPDATE SET name = tmp_x.name;
DROP TABLE tmp_x;
我收到这个错误:
SELECT 0
COPY 1
ERROR: missing FROM-clause entry for table "tmp_x"
LINE 4: ON CONFLICT(name) DO UPDATE SET name = tmp_x.name;
^
Query failed
PostgreSQL said: missing FROM-clause entry for table "tmp_x"
不太确定这里出了什么问题。
如果你看一下 the documentation of the ON CONFLICT
clause,它说的是 "conflict action":
The SET and WHERE clauses in ON CONFLICT DO UPDATE have access to the existing row using the table's name (or an alias)
在您的查询中,目标 table 是 repos
。
tmp_x
是您要插入的数据的来源,但 ON CONFLICT
子句不能 "see" - 它正在查看特定的已计算但失败的行。想想你是否写过这样的东西:
INSERT INTO repos SELECT max(foo_id) FROM tmp_x
显然,无法插入 repos
的行访问 tmp_x
.
如果无法查看被拒绝的数据,整个功能将毫无用处,但如果我们继续阅读:
... and to rows proposed for insertion using the special excluded table.
因此,您需要访问神奇的 table 别名 excluded
,其中包含您尝试插入但发生冲突的值,给您:
INSERT INTO repos SELECT * FROM tmp_x
ON CONFLICT(name) DO UPDATE SET name = excluded.name;
如果为此目的弹出一个假想的 table 名称看起来很奇怪,请考虑在编写触发器时发生类似的事情,您会得到 OLD
和 NEW
(取决于关于您正在编写的触发器类型)。