9

パラメータとして渡された整数値に応じて別のストアドプロシージャを呼び出すストアドプロシージャがPostgreSQL8.4にあります。これらのストアドプロシージャは、1つの整数列との関係を返すように呼び出されます。私が抱えている問題は、外部ストアドプロシージャが常に正しい行数で、ただし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を返すのでしょうか。

4

1 に答える 1

13

of spaはidoutパラメータid()と競合しますRETURNS TABLE (id integer)。Postgresql 8.4は文句を言わず、saner one(spaのid)の代わりにoutパラメーターidから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.ididます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)

hahah列に注意してください

于 2012-07-14T00:47:46.530 に答える