Fonction DROP sans connaître le nombre / type de paramètres?
je garde toutes mes fonctions dans un fichier texte avec 'CREATE OR REPLACE FUNCTION somefunction'
.
Donc, si j'ajoute ou modifie une fonction, je donne juste le fichier à psql.
maintenant si j'ajoute ou supprime des paramètres à une fonction existante, cela crée une surcharge avec le même nom et pour supprimer l'original j'ai besoin de taper tous les types de paramètres dans l'ordre exact qui est un peu fastidieux.
est-ce qu'il y a une sorte de Joker que je peux utiliser pour supprimer toutes les fonctions avec un nom donné pour que je puisse il suffit d'ajouter les lignes DROP FUNCTION
en haut de mon fichier?
5 réponses
vous auriez besoin d'écrire une fonction qui a pris le nom de la fonction, et regardé chaque surcharge avec ses types de paramètres de information_schema
, puis construit et exécuté un DROP
pour chacun.
EDIT: Ce qui s'est avéré être beaucoup plus difficile que je ne le pensais. Il semble que information_schema
ne garde pas les informations paramétriques nécessaires dans son catalogue routines
. Vous devez donc utiliser les tables supplémentaires de PostgreSQL pg_proc
et 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;
j'ai testé avec succès sur une fonction surchargée. Il a été assemblé assez rapidement, mais fonctionne très bien comme une fonction utilitaire. Je recommande de tester davantage avant de l'utiliser en pratique, au cas où j'aurais oublié quelque chose.
recherche de Base
cette requête crée toutes les déclarations DDL nécessaires (simplifié avec cast à 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
sortie:
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);
exécute les commandes (après un contrôle de plausibilité).
le nom de la fonction est sensible à la casse et ne comporte pas de guillemets lorsqu'il est passé sous le paramètre text
pour correspondre à pg_proc.proname
.
the cast to the object identifier type regprocedure
( oid::regprocedure
) rend tous les identificateurs sûrs contre l'injection SQL (par le biais d'identificateurs mal formés malicieusement). Lors de la conversion en text
, le nom de la fonction est double-cité et qualifié de schéma selon le courant search_path
automatiquement si nécessaire.
pg_function_is_visible(oid)
restreint la sélection aux fonctions dans le courant search_path
. Vous pouvez ou ne voulez pas que. Avec la condition pg_function_is_visible(oid)
en place, la fonction est garantie d'être visible.
si vous avez plusieurs fonctions du même nom dans plusieurs schémas, ou des fonctions surchargées avec divers arguments de fonction, 1519510920" tous de ceux-ci seront énumérés séparément. Vous pouvez limiter schéma spécifique(s) ou d'une fonction spécifique paramètre(s), après tout.
Related:
fonction
vous pouvez construire une fonction plpgsql
pour exécuter les instructions immédiatement avec EXECUTE
. Pour Postgres 9.1 ou plus tard:
attention! Il lâche vos fonctions!
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;
appel:
SELECT * FROM f_delfunc('my_function_name');
Ou simplement:
SELECT f_delfunc('my_function_name');
de cette façon, vous n'obtiendrez pas la colonne nom func_dropped
pour la colonne Résultat. Peut pas d'importance pour vous.
la fonction renvoie le nombre de fonctions trouvées et supprimées (aucune exception Elevée) - 0
si aucune n'a été trouvée.
il suppose un (par défaut) search_path
où pg_catalog
n'a pas été déplacé.
Plus dans ces réponses liées:
- Comment le search_path influence de résolution de l'identificateur et le "schéma actuel"
- tronquer tous les tableaux dans une base de données Postgres
- PostgreSQL paramétrée Commande Par / Limite en fonction de table
pour les versions Postgres Plus anciennes que 9.1 ou plus anciennes de la fonction en utilisant regproc
et pg_get_function_identity_arguments(oid)
vérifier l'historique éditer de cette réponse.
Amélioration de l'original réponse afin de prendre schema
en compte, c'est à dire. 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';
version légèrement améliorée de la réponse D'Erwin. En outre, les supports suivant
- 'comme' au lieu de la fonction exacte correspondance de nom
- peut exécuter en 'dry-mode' et 'trace' le SQL pour enlever les fonctions
Code pour copier / coller:
/**
* 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');
Voici la requête que j'ai construite en haut de la solution @Сухой27 qui génère des instructions sql pour laisser tomber toutes les fonctions stockées dans un schéma:
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);