1

カスタムタイプを作成しました

CREATE TYPE rc_test_type AS (a1 bigint);

と関数

CREATE OR REPLACE FUNCTION public.rc_test_type_function(test_table character varying, dummy integer)
  RETURNS rc_test_type AS
$BODY$ 
    DECLARE
    ret rc_test_type;
    query  text;
    BEGIN
    query := 'SELECT count(*) from '  || test_table    ;
    EXECUTE query into ret.a1;  
    RETURN ret;
END $BODY$
  LANGUAGE plpgsql VOLATILE

私が走れば

SELECT * FROM rc_test_type_function('some_table', 1);

私は得る

"a1"
1389

ここまでは順調ですね。

私が走れば

SELECT p FROM (SELECT rc_test_type_function('some_table', s.step) AS p 
FROM  some_other_table s) foo;

私は得る

"p"
"(1389)"
"(1389)"

「some_other_table」には 2 つのレコードしかないためです。罰金。

しかし、私が試してみると

SELECT p.a1 FROM (select rc_test_type_function('some_table', s.step) AS p
FROM some_other_table s) foo;

エラーが発生します

テーブル »p« のサブクエリに FROM 句のエントリがありません

サブクエリが変更されていないので、これは奇妙だと思います。

2 つの質問:

  1. 誰が何が起こっているのか説明できますか?
  2. a1返された配列からフィールド値を抽出するにはどうすればよいですか?
4

1 に答える 1

3

複合型括弧​​で囲みます:

SELECT (p).a1
FROM   (SELECT rc_test_type_function('some_table', s.step) AS p
        FROM   some_other_table s
       ) foo;

あなたの型には単一の列しかありませんが、それでも複合型であり、独自の列名があります。あまり意味がありませんが、それがあなたがそれを構築した方法です。
(単に単純な型を使用するか、DOMAIN代わりに a を使用することをお勧めします。)

ここでマニュアルを引用:

(compositecol).somefield
(mytable.compositecol).somefield

compositecolここでは、テーブル名ではなく列名であること、またはmytable2 番目のケースではスキーマ名ではなくテーブル名であることを示すために、括弧が必要です。

適切な機能

複合型の部分を省略すると、関数は次のように、より安全、シンプル、高速になります。

CREATE OR REPLACE FUNCTION foo(test_table varchar, dummy int, OUT p bigint)
  AS
$func$ 
BEGIN
   EXECUTE format('SELECT count(*) from %I', test_table)  -- !avoid SQLi!
   INTO p;  
END
$func$ LANGUAGE plpgsql;
  • 動的SQLでSQLインジェクションを回避!
  • この場合、OUTパラメーターは構文を簡素化します。DECLARE句はまったく必要ありませんRETURN

さらに良い

CREATE OR REPLACE FUNCTION foo(test_table regclass, dummy int, OUT p bigint)
  AS
$func$ 
BEGIN
   EXECUTE 'SELECT count(*) from ' || test_table
   INTO p;  
END
$func$ LANGUAGE plpgsql;
  • オブジェクト識別子regclassを使用することで、これはスキーマ修飾されたテーブル名でも機能します。そして、SQLi はそもそも不可能です。テーブル名が不正な場合、関数はすぐに失敗し、自動的に変換されたときに自動的に引用されtextます。
于 2013-04-10T14:10:40.047 に答える