带有RETURNS TABLE(id整数)的PostgreSQL存储过程返回所有NULL

时间:2012-07-13 23:24:07

标签: sql postgresql plpgsql

我在PostgreSQL 8.4中有一个存储过程,它根据作为参数传入的整数值调用另一个存储过程。调用那些存储过程,使它们返回一个整数列的关系。我遇到的问题是外部存储过程总是返回具有正确行数但具有所有id的NULL的关系。

这是存储过程简化为最简单的形式:

CREATE OR REPLACE FUNCTION spa(count integer) 
RETURNS TABLE (id integer) AS $$
BEGIN
    RETURN QUERY SELECT generate_series(1, count);
END;
$$ LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION spb(count integer) 
RETURNS TABLE (id integer) AS $$
BEGIN
    RETURN QUERY SELECT generate_series(1, count);
END;
$$ LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION conditional_relation_return(objectType integer, count integer) 
RETURNS TABLE (id integer) AS $$
BEGIN
    IF objectType = 1 THEN
        RETURN QUERY SELECT id FROM spa(count);
    ELSIF objectType = 2 OR objectType = 3 THEN
        RETURN QUERY SELECT id FROM spb(count);
    END IF;

END;
$$ LANGUAGE plpgsql;

如果你打电话:

# select * from conditional_relation_return(1, 2);
 id 
----


(2 rows)

或更具体地说:

# select count(*) from conditional_relation_return(1, 2) where id is null;
 count 
-------
     2
(1 row)

但是,如果您调用其中一个引用的存储过程,则会得到正确的结果:

# select * from spa(2);
 id 
----
  1
  2
(2 rows)

那么为什么conditional_relation_return会返回所有NULL?

1 个答案:

答案 0 :(得分:13)

spa的id与out参数id(RETURNS TABLE (id integer))冲突。 Postgresql 8.4没有抱怨,它从out参数id中选择id而不是saner one(spa的id)。

Postgresql 9.1抱怨您的原始代码:

ERROR:  column reference "id" is ambiguous
LINE 1: SELECT id FROM spa(count)
               ^
DETAIL:  It could refer to either a PL/pgSQL variable or a table column.
QUERY:  SELECT id FROM spa(count)
CONTEXT:  PL/pgSQL function "conditional_relation_return" line 4 at RETURN QUERY

要修复它,请完全限定查询中的ID:

CREATE OR REPLACE FUNCTION conditional_relation_return(
    objectType integer, count integer) 
RETURNS TABLE (id integer) AS $$
BEGIN
    IF objectType = 1 THEN
        RETURN QUERY SELECT x.id FROM spa(count) as x;
    ELSIF objectType = 2 OR objectType = 3 THEN
        RETURN QUERY SELECT x.id FROM spb(count) as x;
    END IF;

END;
$$ LANGUAGE plpgsql;

输出:

test=# select * from conditional_relation_return(1, 2);
 id 
----
  1
  2
(2 rows)

Postgresql尊重您从RETURNS TABLE中选择的列名称。它仍会将x.id插入您id的{​​{1}}。因此,即使您决定重命名RETURNS TABLE返回列的名称,它仍会将RETURNS TABLE插入该名称,例如

x.id

输出:

CREATE OR REPLACE FUNCTION conditional_relation_return(
    objectType integer, count integer) 
RETURNS TABLE (hahah integer) AS $$
BEGIN
    IF objectType = 1 THEN
        RETURN QUERY SELECT x.id FROM spa(count) as x;
    ELSIF objectType = 2 OR objectType = 3 THEN
        RETURN QUERY SELECT x.id FROM spb(count) as x;
    END IF;

END;
$$ LANGUAGE plpgsql;

请注意test=# select * from conditional_relation_return(1, 2); hahah ------- 1 2 (2 rows)