我在Postgres中有这个简单的测试功能(在我的test
模式中)。
CREATE OR REPLACE FUNCTION test.func_001
(
par_id int
)
RETURNS TABLE
(
id int
)
AS
$BODY$
DECLARE
var_id int;
BEGIN
update test.item --- this is a table
set
id = 4
WHERE
id = 44;
return query
select 1000 as id;
END;
$BODY$
LANGUAGE plpgsql;
test.item
表具有一个id列。
尝试运行该功能时出现以下错误。
Query execution failed
Reason:
SQL Error [42702]: ERROR: column reference "id" is ambiguous
Detail: It could refer to either a PL/pgSQL variable or a table column.
Where: PL/pgSQL function test.func_001(integer) line 8 at SQL statement
这个错误似乎很奇怪,是否意味着Postgres正在从返回的表中找到test.item.id
列和id
列之间的冲突/冲突?
怎么来的?这没有任何意义。
我不敢相信,但我在这里看不到其他ID用法。
请注意,如果我仅对此部分进行注释。
-- WHERE
-- id = 44;
然后突然该功能运行正常。
所以看来Postgres在哪里混淆了id 子句带有其他名为id的东西?!
用什么?
这完全是不合逻辑和违反直觉的。
有人可以解释吗?
答案 0 :(得分:3)
子句FUNCTION fx() RETURNS TABLE(x int, y int, ...)
与FUNCTION(OUT x int, OUT y int) RETURNS SETOF record
相同。因此,在您的情况下,存在隐式变量id
,尽管您没有显式使用它。
PostgreSQL设计允许在不使用SQL的情况下生成行。
CREATE OR REPLACE FUNCTION foo(a int)
RETURNS TABLE(b int, c int) AS $$
BEGIN
FOR i IN 1..a
LOOP
b := i; c := i * 10;
RETURN NEXT;
END LOOP;
END;
$$ LANGUAGE plpgsql;
请参见following文档。
还有另一种将函数声明为返回集合的方法,即使用语法RETURNS TABLE(columns)。这等效于使用一个或多个OUT参数,并将功能标记为返回SETOF记录(或SETOF,视情况而定为单个输出参数的类型)。该表示法是在SQL标准的最新版本中指定的,因此,与使用SETOF相比,它可能更具可移植性。
答案 1 :(得分:2)
由id
子句定义的变量RETURNS TABLE
与同名列之间存在名称冲突。
类似的事情会在所有编程语言中引起问题,只有PostgreSQL足以警告您,而不是执行可能并非您想要的事情。
按如下所示对列引用进行限定,以消除歧义:
WHERE test.item.id = 44