1

plpgsql言語の関数で、次のものがあります。

  1. "col" CHARACTER VARYING = 'a';(することができます'b'
  2. "rec" RECORD;保有記録:(SELECT 1 AS "a", 2 AS "b")
  3. "res" INTEGER;

の名前付き列を参照する必要があり"col"ます"rec"。したがって、"col"'b'参照"rec"."b"し、その値を に保存します"res"

4

1 に答える 1

2

plpgsqlでは、匿名レコードタイプの列を名前で参照することはできません。ステートメントの例で列のエイリアスを綴っていてもSELECT、それらは単なるノイズであり、破棄されます。

レコードタイプの要素を名前で参照する場合は、既知のタイプを使用する必要があります。タイプを作成して使用します。

CREATE TYPE my_composite_type(a int, b int);

または、既存のテーブルに関連付けられている行タイプを使用します。テーブル名はデータ型として記述できます。

DECLARE
   rec my_composite_type;
...

次に、のを識別子として使用するための条件文または動的SQLが必要です。"col"

条件付きステートメント:

IF col = 'a' THEN
   res := rec.a;
ELSIF col = 'b' THEN
   res := rec.b;
ELSE
   RAISE EXCEPTION 'Unexpected value in variable "col": %', col;
END IF;

考えられる2つのケースについては、それが方法です。
または動的SQL:

EXECUTE 'SELECT $1.' || col
INTO res
USING rec;

ここでは問題はありませんが、動的SQLを使用したSQLインジェクションには注意してください。任意のデータを保持できる場合は、またはcolでエスケープする必要がありますquote_ident()format()

デモ

動的SQLを使用して、より強力でありながらトリッキーなバリアントを示します。

テスト用の(一時的な!)既知のタイプを作成するための迅速で汚い方法:

CREATE TEMP TABLE rec_ab(a int, b int);

働き:

CREATE OR REPLACE FUNCTION f_test()
  RETURNS integer AS
$func$
DECLARE
    col   text := 'a';  -- can be 'b'
    rec   rec_ab;
    res   int;
BEGIN
    rec := '(1, 2)'::rec_ab;

    EXECUTE 'SELECT $1.' || col
    INTO res
    USING rec;

    RETURN res;
END
$func$
  LANGUAGE plpgsql VOLATILE;

電話:

SELECT f_test();

戻り値:

f_test
----
1
于 2013-01-03T22:59:57.023 に答える