Recently I needed to move objects from PostgreSQL's default schema "public" to another schema. I found this post which shows how to move tables which was great, but I also need to move the functions.
ALTER ROUTINE
to cover both FUNCTION
and PROCEDURE
(added with pg 12).
DO
$do$
DECLARE
_qry text;
BEGIN
SELECT INTO _qry
string_agg(format('ALTER ROUTINE 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';
-- more filters?
RAISE NOTICE '%', _qry; -- inspect query string before executing
-- EXECUTE _qry; -- un-comment to execute
END
$do$;
The rest still applies:
Refine the loop some more (demonstrating only the second query):
DO
$do$
DECLARE
r record;
_qry 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'
-- more filters?
LOOP
_qry := _qry || format(E'\nALTER FUNCTION public.%I(%s) SET SCHEMA new_schema;'
, r.proname, r.params);
END LOOP;
RAISE NOTICE '%', _qry; -- inspect query string before executing
-- EXECUTE _qry; -- un-comment to execute
END
$do$;
Remove unneeded tables from FROM
.
concat()
may be overkill, but format()
simplifies the syntax.
Re-casting the problem as set-based operation is more elegant. One SELECT
with string_agg()
does the job:
DO
$do$
DECLARE
_qry text;
BEGIN
SELECT INTO _qry
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 '%', _qry; -- inspect query string before executing
-- EXECUTE _qry; -- un-comment to execute
END
$do$;