@a_horseは、試行の失敗に関する重大な問題のほとんどを修正します。
ただし、誰もこれを使用しないでください。次の段階的な手順は、最新の PostgreSQL を使用した適切な実装につながるはずです。
フェーズ 1: エラーといたずらを取り除く
リストの後のコンマを削除してSELECT
、構文エラーを修正します。
配列を0
で開始しますが、デフォルトでは で開始し1
ます。これは、必要な場合にのみ行ってください。array_upper()
らと操作すると、予期しない結果につながります。代わりに開始し1
ます。
RETURN
アセンブルされた配列を返すようにタイプを変更しvarchar[]
て、このデモを便利にします。
これまでのところ:
CREATE OR REPLACE FUNCTION foo(tbl varchar, col varchar)
RETURNS varchar[] LANGUAGE plpgsql AS
$BODY$
DECLARE
_r record;
points varchar[] := '{}';
i int := 0;
BEGIN
FOR _r IN
EXECUTE 'SELECT a.'|| quote_ident(col) || ' AS pt
FROM ' || quote_ident (tbl) ||' AS a'
LOOP
i = i + 1; -- reversed order to make array start with 1
points[i] = _r;
END LOOP;
RETURN points;
END;
$BODY$;
フェーズ 2: 不要なものを取り除き、役立つものにする
簡単にするために/のtext
代わりに使用します。ただし、どちらでも機能します。character varying
varchar
単一の列を選択していますが、 type の変数を使用していますrecord
。このようにして、レコード全体が に強制されtext
ます。これには、周囲の括弧が含まれます。ほとんど意味がありません。text
代わりに変数を使用してください。( )に明示的にキャストすると、どの列でも機能します。任意の型を にキャストできます。text
::text
text
変数を初期化しても意味がありませんpoint
。ここから始められNULL
ます。
この場合、内部のテーブルと列のエイリアスEXECUTE
は役に立ちません。動的に実行される SQL には独自のスコープがあります。
plpgsql 関数の final の後にセミコロン ( ;
) は必要ありません。END
を使用して各値を配列に追加する方が簡単||
です。
ほとんど正気です:
CREATE OR REPLACE FUNCTION foo1(tbl text, col text)
RETURNS text[] LANGUAGE plpgsql AS
$func$
DECLARE
point text;
points text[];
BEGIN
FOR point IN
EXECUTE 'SELECT '|| quote_ident(col) || '::text FROM ' || quote_ident(tbl)
LOOP
points = points || point;
END LOOP;
RETURN points;
END
$func$;
フェーズ 3: 最新の PL/pgSQL で輝かせる
テーブル名を として渡すとtext
、あいまいな状況が発生します。またはでSQLiを問題なく防ぐことができますが、 の外側のテーブルでは失敗します。次に、あいまいな値を作成するschema-qualification
を追加する必要があります。「xy」は、テーブル名「xy」またはスキーマ修飾テーブル名「x」.「y」を表すことができます。"""x"".""y""" にエスケープされるため、"x"."y" を渡すことはできません。スキーマ名に追加のパラメーターを使用するか、タイプの 1 つのパラメーターが強制されたときに必要に応じて自動的に引用されるかのいずれかが必要であり、ここではエレガントなソリューションです。format()
quote_ident()
search_path
regclass
regclass
text
新しいformat()
ものは、複数の (または単一の)quote_ident()
呼び出しよりも簡単です。
順序が指定されていません。SELECT
なしで任意の順序で行を返しますORDER BY
。基礎となるテーブルが変更されない限り、結果は通常再現可能であるため、これは安定しているように見えるかもしれません。しかし、それは100%信頼できません。おそらく、何らかの種類のORDER BY
.
最後に、ループする必要はまったくありません。Array コンストラクターでプレーンSELECT
を使用します。
OUT
パラメータを使用してコードをさらに簡素化する
適切な解決策:
CREATE OR REPLACE FUNCTION f_arr(tbl regclass, col text, OUT arr text[])
LANGUAGE plpgsql AS
$func$
BEGIN
EXECUTE format('SELECT ARRAY(SELECT %I::text FROM %s ORDER BY 1)', col, tbl)
INTO arr;
END
$func$;
電話:
SELECT f_arr('myschema.mytbl', 'mycol');