Postgres pl/pgsqlを使用して、次のような動的EXECUTEコマンドを使用してテーブルを作成しようとしています。
...
DECLARE
tblVar varchar := "myTable";
BEGIN
EXECUTE 'CREATE TABLE $1 (
foo integer NOT NULL,
bar varchar NOT NULL)'
USING _tblVar;
...
ただし、引き続きエラーメッセージが表示される
エラー:「$ 1」またはその近くの構文エラー
$1
トークンを使用せず、代わりに文字列myTable
を書き込むと、問題なく動作します。
CREATE呼び出しでの動的ステートメントの使用に制限はありますか?
@filipremが書いたものに加えて、これを正しく行う方法を次に示します。
_...
DECLARE
tbl_var text := 'myTable'; -- I would not use mixed case names ..
BEGIN
EXECUTE '
CREATE TABLE ' || quote_ident(tbl_var) || '(
foo integer NOT NULL,
bar text NOT NULL)';
...
_
quote_ident()
を使用して、SQLインジェクションまたは構文エラーを回避します。非標準文字または予約語で名前を引用します。
また、例の文字列値の前後にある二重引用符を single-quotes に置き換えました。
http://www.postgresql.org/docs/9.1/static/plpgsql-statements.html#PLPGSQL-STATEMENTS-EXECUTING-DYN を参照してください
パラメータシンボルはデータ値にのみ使用できることに注意してください。動的に決定されるテーブルまたは列の名前を使用する場合は、それらをコマンド文字列にテキストで挿入する必要があります。たとえば、動的に選択されたテーブルに対して前述のクエリを実行する必要がある場合は、次のようにすることができます。
EXECUTE 'SELECT count(*) FROM ' || tabname::regclass || ' WHERE inserted_by = $1 AND inserted <= $2' INTO c USING checked_user, checked_date;
以下のコメントに記載されているように、キャストメソッドは、特にCREATEステートメントの場合、常に実行可能であるとは限りません。 format
関数について考えてみましょう。次に例を示します。
EXECUTE format(
'CREATE TABLE %I (%I %I, %I %I)',
v_tabname,
v_col1name, v_col1type,
v_col2name, v_col2type);
言い換えると:
はい、そのような制限があります。テーブル/列名にパラメーターを使用することはできません。これは、動的SQLステートメントのコンパイル時にPostgresqlがクエリを解析できる必要があるためです。パーサーは、使用されている関係を識別できなければなりません。
補足:この制限は、おそらくOracleを含む他のDBMSの動的SQLに適用されます: http://download.Oracle.com/docs/cd/B19306_01/appdev.102/b14261/dynamic.htm#CHDHGHIF =