すべての関数を'CREATE OR REPLACE FUNCTION somefunction'
のテキストファイルに保存します。したがって、関数を追加または変更した場合は、ファイルをpsqlにフィードするだけです。
ここで、既存の関数にパラメーターを追加または削除すると、同じ名前のオーバーロードが作成され、元のパラメーターをすべてのパラメーター型に正確な順序で入力する必要があります。
特定の名前のすべての関数を削除するために使用できるワイルドカードの種類はありますか?ファイルの先頭にDROP FUNCTION
行を追加できますか?
関数名を取得し、information_schema
のパラメータータイプを使用して各オーバーロードを検索する関数を作成し、それぞれに対してDROP
を作成して実行する必要があります。
編集:これは思ったよりずっと難しいことがわかりました。 information_schema
は、必要なパラメータ情報をroutines
カタログに保持していないようです。したがって、PostgreSQLの補足テーブルpg_proc
およびpg_type
を使用する必要があります。
CREATE OR REPLACE FUNCTION udf_dropfunction(functionname text)
RETURNS text AS
$BODY$
DECLARE
funcrow RECORD;
numfunctions smallint := 0;
numparameters int;
i int;
paramtext text;
BEGIN
FOR funcrow IN SELECT proargtypes FROM pg_proc WHERE proname = functionname LOOP
--for some reason array_upper is off by one for the oidvector type, hence the +1
numparameters = array_upper(funcrow.proargtypes, 1) + 1;
i = 0;
paramtext = '';
LOOP
IF i < numparameters THEN
IF i > 0 THEN
paramtext = paramtext || ', ';
END IF;
paramtext = paramtext || (SELECT typname FROM pg_type WHERE oid = funcrow.proargtypes[i]);
i = i + 1;
ELSE
EXIT;
END IF;
END LOOP;
EXECUTE 'DROP FUNCTION ' || functionname || '(' || paramtext || ');';
numfunctions = numfunctions + 1;
END LOOP;
RETURN 'Dropped ' || numfunctions || ' functions';
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
これをオーバーロードされた関数で正常にテストしました。それは一緒にかなり速く投げられましたが、ユーティリティ関数としてうまく機能します。私が何かを見落とした場合に備えて、実際に使用する前にさらにテストすることをお勧めします。
このクエリは、必要なすべてのDDLステートメントを作成します( regprocedure
へのキャストで簡略化されています)。
_SELECT 'DROP FUNCTION ' || oid::regprocedure
FROM pg_proc
WHERE proname = 'my_function_name' -- name without schema-qualification
AND pg_function_is_visible(oid); -- restrict to current search_path ..
-- .. you may or may not want this
_
出力:
_DROP FUNCTION my_function_name(string text, form text, maxlen integer);
DROP FUNCTION my_function_name(string text, form text);
DROP FUNCTION my_function_name(string text);
_
コマンドを実行します(妥当性チェック後)。
関数名は大文字と小文字が区別され、text
パラメータとして渡されたときに二重引用符が追加されず、_pg_proc.proname
_と照合されます。
オブジェクト識別子タイプregprocedure
(_oid::regprocedure
_)にキャストすると、すべての識別子になりますSQLインジェクションに対して安全です(悪意のある不正な識別子による)。 text
に変換する場合、関数名は二重引用符で囲まれ、必要に応じて現在の _search_path
_ に従って自動的にスキーマ修飾されます。
pg_function_is_visible(oid)
選択を現在の関数に制限します _search_path
_ 。あなたはそれを望むかもしれないし、望まないかもしれません。条件pg_function_is_visible(oid)
を設定すると、関数が表示されることが保証されます。
複数のスキーマに同じ名前の複数の関数がある場合、またはさまざまな関数引数を持つオーバーロードされた関数がある場合は、allそれらの個別に表示されます。結局のところ、特定のスキーマまたは特定の関数パラメーターに制限したい場合があります。
関連:
この周りにplpgsql
関数を作成して、 EXECUTE
を指定してステートメントをすぐに実行できます。 Postgres9.1以降の場合:注意!それはあなたの機能を落とします!
_CREATE OR REPLACE FUNCTION f_delfunc(_name text, OUT func_dropped int) AS
$func$
DECLARE
_sql text;
BEGIN
SELECT count(*)::int
, 'DROP FUNCTION ' || string_agg(oid::regprocedure::text, '; DROP FUNCTION ')
FROM pg_proc
WHERE proname = _name
AND pg_function_is_visible(oid)
INTO func_dropped, _sql; -- only returned if trailing DROPs succeed
IF func_dropped > 0 THEN -- only if function(s) found
EXECUTE _sql;
END IF;
END
$func$ LANGUAGE plpgsql;
_
コール:
_SELECT * FROM f_delfunc('my_function_name');
_
あるいは単に:
_SELECT f_delfunc('my_function_name');
_
この方法では、結果列の列name_func_dropped
_を取得しません。あなたには関係ないかもしれません。
関数は、見つかって削除された関数の数を返します(例外は発生しません)-見つからなかった場合は_0
_。
(デフォルト)_search_path
_を想定していますが、_pg_catalog
_は移動されていません。
これらの関連する回答の詳細:
regproc
およびpg_get_function_identity_arguments(oid)
を使用した関数の9.1以前のバージョンより古いバージョンのPostgresの場合、この回答の編集履歴を確認してください。
schema
を考慮に入れるために、元の answer を改善します。 schema.my_function_name
、
select
format('DROP FUNCTION %s(%s);',
p.oid::regproc, pg_get_function_identity_arguments(p.oid))
FROM pg_catalog.pg_proc p
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
WHERE
p.oid::regproc::text = 'schema.my_function_name';
Postgres 10以降、名前がスキーマに対して一意である限り、関数は名前でのみ削除できます。関数ファイルの先頭に次の宣言を配置するだけです。
drop function if exists my_func;
ドキュメント ここ 。
pgsqlは、名前に従ってプロシージャが削除されたときに、同じ名前で引数が異なるプロシージャが複数存在する場合にエラーを生成します。したがって、他のプロシージャに影響を与えずに1つのプロシージャを削除する場合は、次のクエリを使用します。
SELECT 'DROP FUNCTION ' || oid::regprocedure
FROM pg_proc
WHERE oid = {$proc_oid}
これは、スキーマに格納されているすべての関数を削除するためのSQLステートメントを生成する@Сухой27ソリューションの上に構築したクエリです。
WITH f AS (SELECT specific_schema || '.' || ROUTINE_NAME AS func_name
FROM information_schema.routines
WHERE routine_type='FUNCTION' AND specific_schema='a3i')
SELECT
format('DROP FUNCTION %s(%s);',
p.oid::regproc, pg_get_function_identity_arguments(p.oid))
FROM pg_catalog.pg_proc p
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
WHERE
p.oid::regproc::text IN (SELECT func_name FROM f);
アーウィンの回答のわずかに強化されたバージョン。さらに以下をサポート
コピー/貼り付けのコード:
/**
* Removes all functions matching given function name mask
*
* @param p_name_mask Mask in SQL 'like' syntax
* @param p_opts Combination of comma|space separated options:
* trace - output SQL to be executed as 'NOTICE'
* dryrun - do not execute generated SQL
* @returns Generated SQL 'drop functions' string
*/
CREATE OR REPLACE FUNCTION mypg_drop_functions(IN p_name_mask text,
IN p_opts text = '')
RETURNS text LANGUAGE plpgsql AS $$
DECLARE
v_trace boolean;
v_dryrun boolean;
v_opts text[];
v_sql text;
BEGIN
if p_opts is null then
v_trace = false;
v_dryrun = false;
else
v_opts = regexp_split_to_array(p_opts, E'(\\s*,\\s*)|(\\s+)');
v_trace = ('trace' = any(v_opts));
v_dryrun = ('dry' = any(v_opts)) or ('dryrun' = any(v_opts));
end if;
select string_agg(format('DROP FUNCTION %s(%s);',
oid::regproc, pg_get_function_identity_arguments(oid)), E'\n')
from pg_proc
where proname like p_name_mask
into v_sql;
if v_sql is not null then
if v_trace then
raise notice E'\n%', v_sql;
end if;
if not v_dryrun then
execute v_sql;
end if;
end if;
return v_sql;
END $$;
select mypg_drop_functions('fn_dosomething_%', 'trace dryrun');