【问题标题】:PostgreSQL stored procedure with RETURNS TABLE(id integer) returning all NULLs带有 RETURNS TABLE(id integer) 的 PostgreSQL 存储过程返回所有 NULL
【发布时间】:2012-07-13 20:10:51
【问题描述】:

我在 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 呢?

【问题讨论】:

    标签: sql postgresql plpgsql


    【解决方案1】:

    spa 的 id 与 out 参数 id (RETURNS TABLE (id integer)) 冲突。 Postgresql 8.4 没有抱怨,它从参数 id 中选择 id 而不是更理智的一个(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 插入到RETURNS TABLEid。因此,即使您决定重命名您的 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)
    

    注意hahah

    【讨论】:

    • 真有趣。你说的对。 8.4 默默吞下 ambiguous id 错误。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-04
    • 1970-01-01
    • 2011-08-20
    • 2018-06-23
    相关资源
    最近更新 更多