variable_conflict use_variable 不使用 UPSERT 的 ON CONFLICT 子句吗?
Is variable_conflict use_variable not working with ON CONFLICT clause of UPSERT?
我经常使用 variable_conflict use_variable,到目前为止我从未遇到过任何问题。但是,它不适用于 UPSERT
的 ON CONFLICT
子句。这是我的复制品:
CREATE TABLE test(id serial not null,
CONSTRAINT test_pk PRIMARY KEY(id),
category_id INT NOT NULL,
tname TEXT NOT NULL,
CONSTRAINT test_unq UNIQUE(category_id, tname),
some_info TEXT NOT NULL);
CREATE OR REPLACE FUNCTION insert_test(category_id INT, tname TEXT, some_info TEXT)
RETURNS void AS
$BODY$
#variable_conflict use_variable
DECLARE
resultId INTEGER;
BEGIN
INSERT INTO test(category_id, tname, some_info)
SELECT category_id, tname, some_info
ON CONFLICT(category_id, tname) DO NOTHING;
END
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
SELECT insert_test(1, 'Colors', 'Blue');
ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification
CONTEXT: SQL statement "INSERT INTO test(category_id, tname, some_info)
SELECT category_id, tname, some_info
ON CONFLICT(category_id, tname) DO NOTHING"
没有#variable_conflict use_variable一切正常:
CREATE OR REPLACE FUNCTION insert_test2(p_category_id INT, p_tname TEXT, p_some_info TEXT)
RETURNS void AS
$BODY$
DECLARE
resultId INTEGER;
BEGIN
INSERT INTO test(category_id, tname, some_info)
SELECT p_category_id, p_tname, p_some_info
ON CONFLICT(category_id, tname) DO NOTHING;
END
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
SELECT insert_test2(1, 'Colors', 'Blue');
SELECT insert_test2(2, 'Colors', 'Red');
我错过了什么?
ON CONFLICT
子句依赖于索引定义,索引可以在其定义中使用任意表达式(不一定指的是 table 列)。
您可以在 PostgreSQL 9.5.2 中执行此操作:
test=# CREATE TABLE test (id BIGSERIAL NOT NULL PRIMARY KEY, value INT);
CREATE TABLE
test=# CREATE UNIQUE INDEX ix_test ON test (value, (1));
CREATE INDEX
test=# INSERT INTO test (value) VALUES (1);
INSERT 0 1
test=# INSERT INTO test (value) VALUES (1);
ERROR: duplicate key value violates unique constraint "ix_test"
ПОДРОБНОСТИ: Key (value, (1))=(1, 1) already exists.
test=# INSERT INTO test (value) VALUES (1) ON CONFLICT (value, (1)) DO NOTHING;
INSERT 0 0
test=# INSERT INTO test (value) VALUES (1) ON CONFLICT (value, (2)) DO NOTHING;
ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification
test=# INSERT INTO test (value) VALUES (1) ON CONFLICT (value, (id)) DO NOTHING;
ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification
test=# INSERT INTO test (value) VALUES (1) ON CONFLICT (value, (no_such_column)) DO NOTHING;
ERROR: column "no_such_column" does not exist
СТРОКА 1: ...INTO test (value) VALUES (1) ON CONFLICT (value, (no_such_co...
test=# INSERT INTO test (value) SELECT * FROM (VALUES (1)) q (n) ON CONFLICT (value, (n)) DO NOTHING;
ERROR: column "n" does not exist
СТРОКА 1: ...CT * FROM (VALUES (1)) q (n) ON CONFLICT (value, (n)) DO NOT...
ПОДСКАЗКА: There is a column named "n" in table "*SELECT*", but it cannot be referenced from this part of the query.
test=# DROP FUNCTION IF EXISTS fn_test(INT); CREATE FUNCTION fn_test(n INT) RETURNS VOID AS $$ INSERT INTO test (value) VALUES (1) ON CONFLICT (value, (n)) DO NOTHING; $$ LANGUAGE 'sql';
DROP FUNCTION
CREATE FUNCTION
test=# SELECT * FROM fn_test(1);
ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification
КОНТЕКСТ: SQL function "fn_test" during startup
出于某种原因,在进行唯一索引推断时,PostgreSQL 允许在索引表达式中使用变量。
这可能是一个错误,因为我想不出任何合理的理由。
我经常使用 variable_conflict use_variable,到目前为止我从未遇到过任何问题。但是,它不适用于 UPSERT
的 ON CONFLICT
子句。这是我的复制品:
CREATE TABLE test(id serial not null,
CONSTRAINT test_pk PRIMARY KEY(id),
category_id INT NOT NULL,
tname TEXT NOT NULL,
CONSTRAINT test_unq UNIQUE(category_id, tname),
some_info TEXT NOT NULL);
CREATE OR REPLACE FUNCTION insert_test(category_id INT, tname TEXT, some_info TEXT)
RETURNS void AS
$BODY$
#variable_conflict use_variable
DECLARE
resultId INTEGER;
BEGIN
INSERT INTO test(category_id, tname, some_info)
SELECT category_id, tname, some_info
ON CONFLICT(category_id, tname) DO NOTHING;
END
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
SELECT insert_test(1, 'Colors', 'Blue');
ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification
CONTEXT: SQL statement "INSERT INTO test(category_id, tname, some_info)
SELECT category_id, tname, some_info
ON CONFLICT(category_id, tname) DO NOTHING"
没有#variable_conflict use_variable一切正常:
CREATE OR REPLACE FUNCTION insert_test2(p_category_id INT, p_tname TEXT, p_some_info TEXT)
RETURNS void AS
$BODY$
DECLARE
resultId INTEGER;
BEGIN
INSERT INTO test(category_id, tname, some_info)
SELECT p_category_id, p_tname, p_some_info
ON CONFLICT(category_id, tname) DO NOTHING;
END
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
SELECT insert_test2(1, 'Colors', 'Blue');
SELECT insert_test2(2, 'Colors', 'Red');
我错过了什么?
ON CONFLICT
子句依赖于索引定义,索引可以在其定义中使用任意表达式(不一定指的是 table 列)。
您可以在 PostgreSQL 9.5.2 中执行此操作:
test=# CREATE TABLE test (id BIGSERIAL NOT NULL PRIMARY KEY, value INT);
CREATE TABLE
test=# CREATE UNIQUE INDEX ix_test ON test (value, (1));
CREATE INDEX
test=# INSERT INTO test (value) VALUES (1);
INSERT 0 1
test=# INSERT INTO test (value) VALUES (1);
ERROR: duplicate key value violates unique constraint "ix_test"
ПОДРОБНОСТИ: Key (value, (1))=(1, 1) already exists.
test=# INSERT INTO test (value) VALUES (1) ON CONFLICT (value, (1)) DO NOTHING;
INSERT 0 0
test=# INSERT INTO test (value) VALUES (1) ON CONFLICT (value, (2)) DO NOTHING;
ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification
test=# INSERT INTO test (value) VALUES (1) ON CONFLICT (value, (id)) DO NOTHING;
ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification
test=# INSERT INTO test (value) VALUES (1) ON CONFLICT (value, (no_such_column)) DO NOTHING;
ERROR: column "no_such_column" does not exist
СТРОКА 1: ...INTO test (value) VALUES (1) ON CONFLICT (value, (no_such_co...
test=# INSERT INTO test (value) SELECT * FROM (VALUES (1)) q (n) ON CONFLICT (value, (n)) DO NOTHING;
ERROR: column "n" does not exist
СТРОКА 1: ...CT * FROM (VALUES (1)) q (n) ON CONFLICT (value, (n)) DO NOT...
ПОДСКАЗКА: There is a column named "n" in table "*SELECT*", but it cannot be referenced from this part of the query.
test=# DROP FUNCTION IF EXISTS fn_test(INT); CREATE FUNCTION fn_test(n INT) RETURNS VOID AS $$ INSERT INTO test (value) VALUES (1) ON CONFLICT (value, (n)) DO NOTHING; $$ LANGUAGE 'sql';
DROP FUNCTION
CREATE FUNCTION
test=# SELECT * FROM fn_test(1);
ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification
КОНТЕКСТ: SQL function "fn_test" during startup
出于某种原因,在进行唯一索引推断时,PostgreSQL 允许在索引表达式中使用变量。
这可能是一个错误,因为我想不出任何合理的理由。