Vous pouvez affiner davantage la boucle (en montrant uniquement la deuxième requête ):
DO
$do$
DECLARE
r record;
sql text = '';
BEGIN
FOR r IN
SELECT p.proname, pg_get_function_identity_arguments(p.oid) AS params
FROM pg_proc p
JOIN pg_namespace n ON n.oid = p.pronamespace
WHERE nspname = 'public'
-- and other conditions, if needed
LOOP
sql := sql
|| format(E'\nALTER FUNCTION public.%I(%s) SET SCHEMA new_schema;'
,r.proname, r.params);
END LOOP;
RAISE NOTICE '%', sql; -- for viewing the sql before executing it
-- EXECUTE sql; -- for executing the sql
END
$do$;
Points majeurs
-
L'opérateur d'affectation dans plpgsql est
:=
.=
fonctionne, mais n'est pas documenté. -
Supprimer les tables inutiles de
FROM
. -
concat()
peut être exagéré, maisformat()
simplifie la syntaxe.
Meilleure alternative basée sur les ensembles
La refonte du problème en tant qu'opération basée sur les ensembles est plus efficace. Un SELECT avec string_agg()
fait le travail :
DO
$do$
DECLARE
sql text;
BEGIN
SELECT INTO sql
string_agg(format('ALTER FUNCTION public.%I(%s) SET SCHEMA new_schema;'
,p.proname, pg_get_function_identity_arguments(p.oid)), E'\n')
FROM pg_proc p
JOIN pg_namespace n ON n.oid = p.pronamespace
WHERE nspname = 'public';
-- and other conditions, if needed
RAISE NOTICE '%', sql; -- for viewing the sql before executing it
-- EXECUTE sql; -- for executing the sql
END
$do$;