このダミーテーブルの操作
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()
を使用します%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 * fromgetrowdata(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
-
入力パラメータ
_tbl
を(ab-)使用します 3 ここでの目的:- 明確に定義されたタイプを提供します 記録の
- 名前を提供します テーブルの、自動的にスキーマ修飾されます
- 変数として機能します。
-
この関連する回答(最後の章)の詳細な説明:
PL / pgSQL関数をリファクタリングして、さまざまなSELECTクエリの出力を返します