このダミー テーブルの操作
CREATE TEMP TABLE foo (id int, my_num numeric);
INSERT INTO foo VALUES (1, 12.34)
まず、例を単純化してサニタイズしました。
質問に関係のないノイズを削除しました。
RETURNS SETOF void
ほとんど意味がありません。RETURNS void
代わりに使っています。
簡単にするために、text
代わりにを使用します。character varying
動的 SQLを使用する場合は、SQL インジェクションから保護する必要があります。この場合はformat()
withを使用します。他にも方法があります。%I
基本的な問題は、SQL が型と識別子に非常に厳格であることです。動的テーブル名とレコードの動的フィールド名 (元の例では匿名レコード) を操作しています。Pl/pgSQL はこれに対処するための十分な設備が整っていません。Postgres は匿名レコードの中身を知りません。既知のタイプにレコードを割り当てた後でのみ、個々のフィールドを参照できます。動的な名前でレコードのフィールドを設定
しようとする、密接に関連する質問があります:動的 SQL を使用して複合変数フィールドの値を設定する方法
基本機能
CREATE OR REPLACE FUNCTION getrowdata1(table_name text, id int)
RETURNS void AS
$func$
DECLARE
srowdata record;
reqfield text := 'my_num'; -- assigning at declaration time for convenience
value numeric;
BEGIN
RAISE NOTICE 'id: %', id;
EXECUTE format('SELECT * FROM %I WHERE id = $1', table_name)
USING id
INTO srowdata;
RAISE NOTICE 'srowdata: %', srowdata;
RAISE NOTICE 'srowdatadata.my_num: %', srowdata.my_num;
/* This does not work, even with dynamic SQL
EXECUTE format('SELECT ($1).%I', reqfield)
USING srowdata
INTO value;
RAISE NOTICE 'value: %', value;
*/
END
$func$ LANGUAGE plpgsql;
電話:
SELECT * from getrowdata1('foo', 1);
コメントされた部分は例外を発生させます:
レコード データ型の列 "my_num" を識別できませんでした: SELECT * from getrowdata(1,'foo')
hstore
これには、追加モジュールhstoreをインストールする必要があります。データベースごとに 1 回:
CREATE EXTENSION hstore;
次に、すべてが次のように機能します。
CREATE OR REPLACE FUNCTION getrowdata2(table_name text, id int)
RETURNS void AS
$func$
DECLARE
hstoredata hstore;
reqfield text := 'my_num';
value numeric;
BEGIN
RAISE NOTICE 'id: %', id;
EXECUTE format('SELECT hstore(t) FROM %I t WHERE id = $1', table_name)
USING id
INTO hstoredata;
RAISE NOTICE 'hstoredata: %', hstoredata;
RAISE NOTICE 'hstoredata.my_num: %', hstoredata -> 'my_num';
value := hstoredata -> reqfield;
RAISE NOTICE 'value: %', value;
END
$func$ LANGUAGE plpgsql;
電話:
SELECT * from getrowdata2('foo', 1);
多形型
追加のモジュールをインストールしない代替。
レコード変数に行全体を選択するため、定義ごとに適切に定義された型があります。これを使って。キーワードは多相型です。
CREATE OR REPLACE FUNCTION getrowdata3(_tbl anyelement, id int)
RETURNS void AS
$func$
DECLARE
reqfield text := 'my_num';
value numeric;
BEGIN
RAISE NOTICE 'id: %', id;
EXECUTE format('SELECT * FROM %s WHERE id = $1', pg_typeof(_tbl))
USING id
INTO _tbl;
RAISE NOTICE '_tbl: %', _tbl;
RAISE NOTICE '_tbl.my_num: %', _tbl.my_num;
EXECUTE 'SELECT ($1).' || reqfield -- requfield must be SQLi-safe or escape
USING _tbl
INTO value;
RAISE NOTICE 'value: %', value;
END
$func$ LANGUAGE plpgsql;
電話:
SELECT * from getrowdata3(NULL::foo, 1);
-> SQLfiddle