その場でビューを作成するようにしています。
私の場合は、EAVスタイルのテーブルのピボットビューです。
2つの属性を含むテーブルを想定して、トリガー関数(PL/Pythonで記述)内で実行される次のようなステートメントを使用します。
CREATE OR REPLACE VIEW pivot_eav AS
SELECT ct.id,
ct.attr1,
ct.attr2
FROM crosstab(
'
SELECT entity, attribute, value
FROM eav_table
ORDER BY 1
'::text,
'
VALUES (''attr1''), (''attr2'')
'::text
)
AS ct(id text,
attr1 text,
attr2 text
);
しかし、今では、作成時に2つの属性の名前がわかりません。実行時に挿入する必要があります。その場でステートメントを作成して実行できます。実際、それは私が現時点で行っていることです。
"""
CREATE OR REPLACE VIEW pivot_eav AS
SELECT ct.id,
ct.attr1,
ct.attr2
FROM crosstab(
'
SELECT entity, attribute, value
FROM eav_table
ORDER BY 1
'::text,
'
VALUES (''{0}''), (''{1}'')
'::text
)
AS ct(id text,
{0} text,
{1} text
);
""".format("attr1", "attr2")
しかし、入力が実行されるため、これは非常に安全ではないことを私は知っています。
私はこのような準備されたステートメントを使おうとしました:
CREATE OR REPLACE VIEW pivot_eav AS
SELECT ct.id,
ct.attr1,
ct.attr2
FROM crosstab(
'
SELECT entity, attribute, value
FROM eav_table
ORDER BY 1
'::text,
'
VALUES (''$1''), (''$2'')
'::text
)
AS ct(id text,
$1 text,
$2 text
);
これは合法ではないようです。
ドル記号のエスケープを使用して、最初のプレースホルダーを回避することができましたが、それでも2番目のオカレンスはそれらの位置では合法ではないようです!?
名前がリテラルとして使用されているため、その場所でドルエスケープを使用することもできませんでした。
私の質問:
プリペアドステートメントのプレースホルダーは特別な用途しかありません。 (プログラミング言語の文字列補間など、任意の位置で使用できます。)
もしそうなら、その声明をまとめる別の安全な方法はありますか?
ロビン
CREATEステートメントを含むDDLクエリは準備できません。
また、作成可能なDMLクエリであっても、識別子にパラメータを使用することはできません。リテラルが許可されるクエリ内の場所で許可されます。
別の方法として、PL/Pythonが動的SQLに提供する専用関数を使用して、列名をクエリに安全に挿入できます。plpy.quote_ident(string)
:
https://www.postgresql.org/docs/current/static/plpython-util.html