2016-06-17 9 views
0

私はテーブルが存在するかどうかをチェックする単純な関数をpostgresqlに書きたいと思います。 postgresqlのドキュメントでは、私の引数を$ plusのargで参照することができますが、関数の作成中にエラーが発生します。PostgreSQL - 関数でargsを使うことはできません

はここに私の関数である:関数内

CREATE OR REPLACE FUNCTION delete_if_exists(table_name text) RETURNS void 
AS $$ 
BEGIN 

IF EXISTS(SELECT * FROM $1) 
THEN 
delete from $1; 
END IF; 
RETURN; 

END; 
$$ LANGUAGE plpgsql; 

enter image description here

+0

パラメータをテーブル名として使用することはできません。動的SQLを使用する必要があります。https://www.postgresql.org/docs/current/static/plpgsql-statements.html#PLPGSQL-STATEMENTS-EXECUTING-DYN –

答えて

0

変数は、単に文字列に補間されていない、彼らは準備されたクエリにパラメータとして渡されます。そのため、計画を変更するクエリの一部(表名や列名など)では、これらを直接使用することはできません。

これを行うには、動的SQLを使用する必要があります。つまり、プログラムで文字列を作成して実行する必要があります。 Executing Dynamic SQL in the manualを参照してください。

誤ってセキュリティ上の問題が発生しやすいので、動的SQLを作成するときは常に注意が必要です。最低限、正しいエスケープ・メカニズムを使用するべきですが、関数が期待しているテーブル名をホワイトリストまたはパターンマッチさせたいと思うこともあります。

the format() functionさん%Iプレースホルダ使用して引用正しいの例:あなたもかなり長い関数を読み込むする方がはるかに簡単です位置識別子、より、変数の名前を使用することができます

EXECUTE format('delete from %I;', $1); 

注:

EXECUTE format('delete from %I;', table_name); 

実際には書かれているように意味をなさないので、私はそれがあまりに単純化された例であると推測しているので、完全な例は変更しようとしません。

0

識別子(テーブル名、列名)を関数に渡す場合は、execute the query dynamicallyが必要です。さらに、フィルタがないDELETE FROMの代わりに、TRUNCATEを使用する必要があります。これは、これが高速で、ハードディスクをクリーンアップするためです(下側では、変更を元に戻すことはできません)。

CREATE FUNCTION delete_if_exists(table_name text) RETURNS void AS $$ 
BEGIN 
    -- Just try to TRUNCATE 
    EXECUTE format('TRUNCATE %I', table_name); 
EXCEPTION 
    WHEN OTHERS THEN 
     NULL; -- If the table does not exist, an error is thrown, just ignore it 
END; 
$$ LANGUAGE plpgsql; 
関連する問題