Postgres 10 для столбца конфликта имеет то же имя, что и столбец в возвращаемой таблице = неоднозначный
У меня есть следующее определение таблицы:
CREATE TABLE test.table_on_conflict (
a INTEGER NOT NULL,
b INTEGER,
CONSTRAINT table_pkey PRIMARY KEY(a)
)
WITH (oids = false);
и определение функции:
CREATE OR REPLACE FUNCTION test.update_on_conflict (
_a integer,
_b integer
)
RETURNS TABLE (
a integer,
b integer
) AS
$body$
BEGIN
INSERT INTO test.table_on_conflict (a, b)
SELECT _a, _b
ON CONFLICT (a) DO UPDATE SET b = EXCLUDED.b;
RETURN QUERY
SELECT t.a, t.b
FROM test.table_on_conflict t
WHERE t.a = _a;
END;
$body$
LANGUAGE 'plpgsql'
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER
COST 100 ROWS 1000;
Поскольку в возвращаемой таблице есть столбец "a", ON CONFLICT (a) DO UPDATE SET... выдает ошибку:
ERROR: column reference "a" is ambiguous
LINE 3: ON CONFLICT (a) DO UPDATE SET b = EXCLUDED.b
^
DETAIL: It could refer to either a PL/pgSQL variable or a table column.
QUERY: INSERT INTO test.table_on_conflict (a, b) SELECT _a, _b ON CONFLICT (a) DO UPDATE SET b = EXCLUDED.b
CONTEXT: PL/pgSQL function test.update_on_conflict(integer,integer) line 4 at SQL statement
Есть ли способ устранить неоднозначность без использования имени ограничения?
1 ответ
Решение
Я вижу два разных решения:
Сначала упростим вашу функцию до функции SQL:
CREATE OR REPLACE FUNCTION update_on_conflict (_a integer, _b integer)
RETURNS TABLE (a integer, b integer) AS
$body$
INSERT INTO table_on_conflict (a, b)
values (_a, _b)
ON CONFLICT (a) DO UPDATE
SET b = EXCLUDED.b
returning *;
$body$
LANGUAGE sql;
Если вам нужен PL/pgSQL (потому что у вас есть другой код, который вы не показали нам), вы можете объявить функцию как RETURNS setof table_on_conflict
CREATE OR REPLACE FUNCTION update_on_conflict (_a integer, _b integer)
RETURNS setof table_on_conflict
AS
$body$
begin
return query
INSERT INTO table_on_conflict (a, b)
values (_a, _b)
ON CONFLICT (a) DO UPDATE SET b = EXCLUDED.b
returning *;
end;
$body$
LANGUAGE plpgsql;
Отдельный select
не нужно ни в коем случае. Вы можете напрямую вернуть результат оператора INSERT.
Не связано, но: название языка является идентификатором. Не помещайте это в одинарные кавычки.