Drop all functions in a namespace? (Execute generated DDL commands?)
我正在尝试编写一个删除命名空间中所有函数的命令。 我已经找到了一个生成drop函数脚本的命令:
1 2 3 4 | SELECT 'DROP FUNCTION ' || ns.nspname || '.' || proname || '(' || oidvectortypes(proargtypes) || ');' FROM pg_proc INNER JOIN pg_namespace ns ON (pg_proc.pronamespace = ns.oid) WHERE ns.nspname = 'public' ORDER BY proname; |
资料来源:http://www.postgresonline.com/journal/archives/74-How-to-delete-many-functions.html
这将产生类似于:
1 2 3 4 5 | ?COLUMN? ------------------------------------------ DROP FUNCTION public.function1(BIGINT); DROP FUNCTION public.function2(); DROP FUNCTION public.function3(text); |
但是,我无法弄清楚如何更改代码,以便实际删除函数 - 而不是仅生成命令。
有任何想法吗?
Postgres 11中的系统目录已更改! (
- 如何删除PostgreSQL中的所有函数?
看起来像这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | CREATE OR REPLACE FUNCTION public.f_delfunc(_schema text, _del text = '') RETURNS text AS $func$ DECLARE _sql text; _ct text; BEGIN SELECT INTO _sql, _ct string_agg('DROP ' || CASE p.proisagg WHEN TRUE THEN 'AGGREGATE ' ELSE 'FUNCTION ' END || quote_ident(n.nspname) || '.' || quote_ident(p.proname) || '(' || pg_catalog.pg_get_function_identity_arguments(p.oid) || ')' , E' ' ) ,COUNT(*)::text FROM pg_catalog.pg_proc p LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace WHERE n.nspname = _schema; -- AND p.proname ~~* 'f_%'; -- Only selected funcs? -- AND pg_catalog.pg_function_is_visible(p.oid) -- Only visible funcs? IF _ct = '0' THEN RETURN 'Found 0 functions to delete'; ELSIF LOWER(_del) = 'del' THEN -- Actually delete! EXECUTE _sql; RETURN _ct || E' functions deleted: ' || _sql; ELSE -- Else only show SQL. RETURN _ct || E' functions to delete: ' || _sql; END IF; END $func$ LANGUAGE plpgsql; |
致电显示:
1 | SELECT f_delfunc('public'); -- 2nd parameter is covered by default. |
致电删除:
1 | SELECT f_delfunc('public','del'); |
主要观点
-
你需要动态SQL。使用带有
EXECUTE 的plpgsql函数或DO语句(PostgreSQL 9.0+)。 -
请注意函数
pg_get_function_identity_arguments() 和pg_function_is_visible 的使用。后者可以省略。它是一种安全措施,因此您不会删除当前用户search_path 之外的功能。 -
我添加了一个"安全模式"。仅在
$2 = 'del' 时删除。否则只显示生成的SQL。 -
请注意,如果该函数存在于您删除的架构中,则该函数将自行删除。
-
我还添加了
quote_ident() 来防范SQLi。考虑以下:
1 2 3 4 | CREATE FUNCTION"; DELETE FROM users;"() RETURNS INT AS 'SELECT 1' LANGUAGE SQL; |
-
如果对任何涉及的函数存在依赖性,则会失败。可以通过添加
CASCADE 来解决,但我在这里没有这样做,因为它使功能更加危险。
有关:
- DROP FUNCTION不知道参数的数量/类型?
- 如何获取函数参数列表(所以我可以删除一个函数)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | -- DROP FUNCTION public.f_deleteAllFunctions(); CREATE OR REPLACE FUNCTION public.f_deleteAllFunctions() RETURNS TABLE(functiondef CHARACTER VARYING) AS $BODY$ DECLARE var_r record; var_query TEXT; BEGIN FOR var_r IN( SELECT ns.nspname || '.' || proname || '(' || oidvectortypes(proargtypes) || ');' AS nombreFuncion FROM pg_proc INNER JOIN pg_namespace ns ON (pg_proc.pronamespace = ns.oid) WHERE ns.nspname = 'public' ORDER BY proname ) LOOP functionDef := 'DROP FUNCTION ' ||var_r.nombreFuncion; RAISE NOTICE '%', functionDef; EXECUTE functionDef; RETURN NEXT; END LOOP; END $BODY$ LANGUAGE plpgsql VOLATILE COST 100 ROWS 1000; ALTER FUNCTION public.f_deleteAllFunctions() OWNER TO postgres; SELECT * FROM f_deleteAllFunctions(); |
没有存储过程的我的版本
1 2 3 4 5 6 7 8 | DO $$DECLARE command text; BEGIN command = (SELECT 'DROP FUNCTION ' || proname || '(' || oidvectortypes(proargtypes) || ')' FROM pg_proc INNER JOIN pg_namespace ns ON (pg_proc.pronamespace = ns.oid) WHERE proname='functioniliketodrop' ORDER BY proname); EXECUTE command; END$$; |
对于生成一组命令的任何SQL表达式:
1 2 3 4 5 6 7 8 9 10 | BEGIN; CREATE FUNCTION _execute(text) RETURNS BOOLEAN LANGUAGE plpgsql AS $$ BEGIN raise info 'Execute: %', $1; EXECUTE $1; END; $$; SELECT COUNT(_execute(__SQL__)); -- __SQL__ is your command-generating statement DROP FUNCTION _execute(text); END; |
只需将查询的输出复制+粘贴到