列引用“ id”不明确-它可以引用PL / pgSQL变量或表列

时间:2018-11-08 09:29:58

标签: postgresql plpgsql

我在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的东西?!

用什么?

这完全是不合逻辑和违反直觉的。

有人可以解释吗?

2 个答案:

答案 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