Har*_*wig 4 sql postgresql dynamic-sql plpgsql
我正在尝试编写一个命令来删除命名空间中的所有函数。我已经找到了一个可以生成删除函数脚本的命令:
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;
Run Code Online (Sandbox Code Playgroud)
资料来源:http ://www.postgresonline.com/journal/archives/74-How-to-delete-many-functions.html
这将生成类似以下内容的内容:
?column?
------------------------------------------
DROP FUNCTION public.function1(bigint);
DROP FUNCTION public.function2();
DROP FUNCTION public.function3(text);
Run Code Online (Sandbox Code Playgroud)
但是,我不知道如何更改代码,以便实际上删除函数 - 而不是仅生成命令。
有任何想法吗?
Postgres 11中的系统目录发生了变化!(prokind而不是proisagg)参见:
可能看起来像这样:
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'\n'
)
,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:\n' || _sql;
ELSE -- Else only show SQL.
RETURN _ct || E' functions to delete:\n' || _sql;
END IF;
END
$func$ LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)
来电显示:
SELECT f_delfunc('public'); -- 2nd parameter is covered by default.
Run Code Online (Sandbox Code Playgroud)
调用删除:
SELECT f_delfunc('public','del');
Run Code Online (Sandbox Code Playgroud)
为此,您需要动态 SQL。将plpgsql 函数或DO 语句(PostgreSQL 9.0+) 与EXECUTE.
请注意函数pg_get_function_identity_arguments()和pg_function_is_visible的使用。后者可以省略。这是一种保护措施,因此您不会删除当前用户的search_path.
我添加了“安全模式”。仅删除如果$2 = 'del'. 否则只显示生成的 SQL。
请注意,如果该函数位于您从中删除的架构中,它将删除自身。
我还添加了quote_ident()防范SQLi 的功能。考虑以下:
CREATE FUNCTION "; DELETE FROM users;"()
RETURNS int AS
'SELECT 1'
LANGUAGE sql;
Run Code Online (Sandbox Code Playgroud)
CASCADE,但我在这里没有这样做,因为它使该函数更加危险。有关的:
| 归档时间: |
|
| 查看次数: |
3839 次 |
| 最近记录: |