12

Right now I have to use query to get the command in text file. Then remove double quote from them. And finally, run that file in psql shell.

How can drop all of my functions in PostgreSQL in a single step?

Evan Carroll
65.6k50 gold badges257 silver badges508 bronze badges
asked Dec 3, 2015 at 2:33
3
  • 5
    Don't use raw ||. Use quote_ident or the format function with the %I format-specifier. That way identifier quoting is handled properly. Use a DO block to EXECUTE the queries you generate to avoid doing it in multiple steps. See dynamic-sql, postgresql Commented Dec 3, 2015 at 2:44
  • I am reading on your given links. Thank you. Commented Dec 3, 2015 at 2:52
  • 1
    Removed the lengthy steps as they're relatively irrelevant. Also edited the title, they're not "your" functions unless you're testing for ownership. They're just functions in a schema that you can drop. Commented Jan 19, 2018 at 6:41

4 Answers 4

20

To drop all functions (including aggregates) in a given schema (be careful with this!):

Postgres 11 or later

  • Procedures have been added.
  • The system catalog pg_proc slightly changed: prokind replaces proisagg and proiswindow - and also tags functions and the new procedures
DO
$do$
DECLARE
 _sql text;
BEGIN
 SELECT INTO _sql
 string_agg(format('DROP %s %s;'
 , CASE prokind
 WHEN 'f' THEN 'FUNCTION'
 WHEN 'a' THEN 'AGGREGATE'
 WHEN 'p' THEN 'PROCEDURE'
 WHEN 'w' THEN 'FUNCTION' -- window function (rarely applicable)
 -- ELSE NULL -- not possible in pg 11
 END
 , oid::regprocedure)
 , E'\n')
 FROM pg_proc
 WHERE pronamespace = 'public'::regnamespace -- schema name here!
 -- AND prokind = ANY ('{f,a,p,w}') -- optionally filter kinds
 ;
 IF _sql IS NOT NULL THEN
 RAISE NOTICE '%', _sql; -- debug / check first
 -- EXECUTE _sql; -- uncomment payload once you are sure
 ELSE 
 RAISE NOTICE 'No fuctions found in schema %', quote_ident(_schema);
 END IF;
END
$do$;

The schema name is case sensitive in this context.
The executing role needs to have the necessary privileges of course.

You might add CASCADE like demonstrated by mehmet but that will also drop depending objects, recursively - not just functions. Makes it even more dangerous. You better know exactly what you are doing.

Related, with more explanation:

Postgres 10 or older

DO
$do$
DECLARE
 _sql text;
BEGIN
 SELECT INTO _sql
 string_agg(format('DROP %s %s;'
 , CASE WHEN proisagg THEN 'AGGREGATE' ELSE 'FUNCTION' END
 , oid::regprocedure)
 , E'\n')
 FROM pg_proc
 WHERE pronamespace = 'public'::regnamespace; -- schema name here!
 IF _sql IS NOT NULL THEN
 RAISE NOTICE '%', _sql; -- debug / check first
 -- EXECUTE _sql; -- uncomment payload once you are sure
 ELSE 
 RAISE NOTICE 'No fuctions found in schema %', quote_ident(_schema);
 END IF;
END
$do$;
answered Dec 3, 2015 at 11:20
2
  • 1
    @ErwinBrandstetter do you a similar method to drop all custom types? I could post a question, if you haven't answered this, here or at SO. Commented Oct 12, 2018 at 8:54
  • 1
    @ypercubeTM: A similar procedure should get it done. But you need to define "custom type". Only from a given schema? Row types of user tables would qualify as "custom types", too, but cannot be dropped while the table depends on it. I suggest you start a new question with defining info. Commented Oct 18, 2018 at 23:42
5

I had to touch-up Erwin's answer above for several cases:

1) If you had an aggregate function in the schema that triggered and error. 2) If you wanted to drop functions in two schemas and the function that deletes is in the first, it got deleted too. 3) If functions depended on each other. Use cascade to force-drop.

Here it is:

create or replace function data.delete_all_functions(schema_in text)
 returns void as
$$
declare
 qry text;
begin
 select into qry string_agg(
 format(
 case when proname = 'delete_all_functions' then '-- %s;' -- don't delete self
 when proisagg then 'drop aggregate if exists %s cascade;'
 else 'drop function if exists %s cascade;'
 end,
 oid :: regprocedure
 ),
 E'\n'
 )
 from pg_proc
 where pronamespace = schema_in :: regnamespace;
 if qry is not null then
 execute qry;
 raise notice 'deleted all functions in schema: %', schema_in;
 else
 raise notice 'no functions to delete in schema: %', schema_in;
 end if;
end
$$
language plpgsql;
answered Sep 11, 2018 at 22:48
3
  • Oh, just saw your added answer. Yes, your additions all make sense. Commented Sep 12, 2018 at 1:23
  • @ErwinBrandstetter sorry I was little too impatient :) Commented Sep 12, 2018 at 15:26
  • pg_proc.proisagg is no longer with us with pg version 11 Commented Mar 6, 2019 at 14:35
1

I took the correct answer above and made it into a function that generated the script passing in the schema name and a search pattern as params. I keep a few of these in my db during design phase but either lock them down or remove them from production.

CREATE FUNCTION extfunc.systool_generatescript_functiondelete(
 schemaname character varying,
 searchpattern character varying)
 RETURNS character varying
 LANGUAGE 'plpgsql'
 COST 100
 VOLATILE 
 
AS $BODY$
Declare
_sql text;
BEGIN
 SELECT INTO _sql
 string_agg(format('DROP %s %s;'
 , CASE prokind
 WHEN 'f' THEN 'FUNCTION'
 WHEN 'a' THEN 'AGGREGATE'
 WHEN 'p' THEN 'PROCEDURE'
 WHEN 'w' THEN 'FUNCTION' -- window function (rarely applicable)
 -- ELSE NULL -- not possible in pg 11
 END
 , oid::regprocedure)
 , E'\n')
 FROM pg_proc
 WHERE pronamespace = schemaname::regnamespace -- schema name here!
 -- AND prokind = ANY ('{f,a,p,w}') -- optionally filter kinds
 AND oid::regprocedure::varchar LIKE ('%' || searchpattern || '%');
 RETURN _sql;
 
END;
$BODY$;
answered Aug 14, 2020 at 3:31
0

The one-step variants are hard to understand, so here are simple steps on HeidiSQL, but I hope you can do it on any DB viewer. Make a table that generates queries to delete functions

SELECT 'DROP FUNCTION "' || p.proname || '";'
FROM 
 pg_catalog.pg_namespace n
JOIN 
 pg_catalog.pg_proc p ON 
 p.pronamespace = n.oid
WHERE 
 p.prokind = 'f'
AND
 n.nspname = 'public';

or

SELECT 
 'DROP FUNCTION "' || ROUTINE_NAME || '";'
FROM 
 information_schema.routines
WHERE 
 routine_type = 'FUNCTION'
AND
 routine_schema = 'public';

So here you see some rows:

DROP FUNCTION "a_i_aspnetuserclaims_f";
DROP FUNCTION "a_d_aspnetroleclaims_f";
DROP FUNCTION "a_d_aspnetuserclaims_f";
DROP FUNCTION "a_d_channels_f";
DROP FUNCTION "a_d_aspnetuserlogins_f";

Select all rows, then click "Export" as text on your buffer. So you could insert it to execute: enter image description here

answered Feb 10, 2022 at 17:07
1
  • I liked this approx : ``` SELECT 'DROP FUNCTION ' || p.proname || '(' || oidvectortypes(proargtypes) ||');' FROM pg_catalog.pg_namespace n JOIN pg_catalog.pg_proc p ON p.pronamespace = n.oid WHERE p.prokind = 'f' AND n.nspname = 'public'; ``` works even better Commented Sep 2, 2022 at 17:53

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.