我刚开始使用PL / pgSQL,我正在尝试创建一个函数来查找现有行的ID,或者如果找不到则会插入一个新行,并返回新的ID。
下面函数中包含的查询可以自行正常工作,并且函数可以很好地创建。但是,当我尝试运行它时,我收到一条错误,指出“错误:列引用”id“不明确”。任何人都可以确定我的问题,或建议更合适的方法吗?
create or replace function sp_get_insert_company(
in company_name varchar(100)
)
returns table (id int)
as $$
begin
with s as (
select
id
from
companies
where name = company_name
),
i as (
insert into companies (name)
select company_name
where not exists (select 1 from s)
returning id
)
select id
from i
union all
select id
from s;
end;
$$ language plpgsql;
这就是我调用函数的方式:
select sp_get_insert_company('TEST')
这是我得到的错误:
SQL错误[42702]:错误:列引用“id”不明确
细节:它可以指PL / pgSQL变量或表列 其中:PL / pgSQL函数sp_get_insert_company(字符变化)SQL语句中的第3行
答案 0 :(得分:1)
正如消息所说,id
在那里两次。一旦进入查询,一旦在表的定义中返回类型。不知怎的,这种冲突。
尝试在任何地方对列表达式进行限定。
...
with s as (
select
companies.id
from
companies
where name = company_name
),
i as (
insert into companies (name)
select company_name
where not exists (select 1 from s)
returning companies.id
)
select i.id
from i
union all
select s.id
from s;
...
通过限定列表达式,DBMS不再将表id
与返回类型定义中的id
混淆。
下一个问题是,SELECT
没有目标。它会告诉您改为PERFORM
。但我想你想要返回结果。将身体改为
...
RETURN QUERY (
with s as (
select
companies.id
from
companies
where name = company_name
),
i as (
insert into companies (name)
select company_name
where not exists (select 1 from s)
returning companies.id
)
select i.id
from i
union all
select s.id
from s);
...
这样做。
答案 1 :(得分:1)
在您显示的功能中,不需要returns table (id int)
。 假设总是返回一个整数ID。简化为RETURNS int
。这也使ERROR: column reference "id" is ambiguous
消失,因为我们隐式删除了OUT
参数id
(在整个功能块中可见)。
也不需要LANGUAGE plpgsql
。可以简单地LANGUAGE sql
,那么您也不需要添加RETURNS QUERY
。所以:
CREATE OR REPLACE FUNCTION sp_get_insert_company(_company_name text)
RETURNS int AS
$func$
WITH s as (
select c.id -- still good style to table-qualify all columns
from companies c
where c.name = _company_name
),
i as (
insert into companies (name)
select _company_name
where not exists (select 1 from s)
returning id
)
select s.id from s
union all
select i.id from i
LIMIT 1; -- to optimize performance
$func$ LANGUAGE sql;
除了之外仍然存在并发问题。在这个密切相关的答案中找到适合您未公开的Postgres版本的解决方案: