10

We are using PostgreSQL. My requirement is to delete unused sequences from my database. For example, if I create any table through my application, one sequence will be created, but for deleting the table we are not deleting the sequence, too. If want to create the same table another sequence is being created.

Example: table: file; automatically created sequence for id coumn: file_id_seq

When I delete the table file and create it with same name again, a new sequence is being created (i.e. file_id_seq1). I have accumulated a huge number of unused sequences in my application database this way.

How to delete these unused sequences?

Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228
user1023877
  • 193
  • 2
  • 3
  • 13

5 Answers5

20

A sequence that is created automatically for a serial column is deleted automatically, when the column (or its table) is dropped. The problem you describe should not exist to begin with. Only very old versions of PostgreSQL did not do that. 7.4 or older?

Solution for the problem

This query will generate the DDL commands to delete all "unbound" sequences in the database it is executed in:

SELECT string_agg('DROP SEQUENCE ' || c.oid::regclass, '; ') || ';' AS ddl
FROM   pg_class       c
LEFT   JOIN pg_depend d ON d.refobjid = c.oid
                       AND d.deptype <> 'i'
WHERE  c.relkind = 'S'
AND    d.refobjid IS NULL;

The cast to regclass in c.oid::regclass automatically schema-qualifies sequence names where necessary according to the current search_path. See:

Result:

DROP SEQUENCE foo_id_seq;
DROP SEQUENCE bar_id_seq;
...

Execute the result to drop all sequences that are not bound to a serial column (or any other column). Study the meaning of columns and tables here.

Careful! These sequences might be in use otherwise. There are use cases where sequences are created as standalone objects. For instance, if you want multiple columns to share one sequence. You should know exactly what you are doing.

However, you cannot delete sequences bound to a serial column this way. So the operation is safe in this respect.

DROP SEQUENCE test_id_seq;

Result:

ERROR:  cannot drop sequence test_id_seq because other objects depend on it
DETAIL:  default for table test column id depends on sequence test_id_seq
HINT:  Use DROP ... CASCADE to drop the dependent objects too.
Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228
  • What I do is same like your solution. It is correct way or not i dont know. i get all the sequences. then saved in file.sql then i run the file. code is: – user1023877 Nov 26 '11 at 09:16
  • `\o d:/test1.sql SELECT 'drop sequence ' || c.relname || ';' FROM pg_class c WHERE (c.relkind = 'S'); \o \i d:/test1.sql` – user1023877 Nov 26 '11 at 09:22
  • @user1023877: That tries to drop any and all sequences. Which should fail if any "bound" sequence exists. – Erwin Brandstetter Nov 26 '11 at 13:12
  • 1
    so This is not the proper solution right, so i will move on to another solution .thank you. – user1023877 Nov 28 '11 at 05:34
  • yes, i will move on to the another solution means your solution only. thank you. – user1023877 Nov 28 '11 at 11:46
  • I'm running postgres 9.3.4 and a table's sequence is NOT deleted for me when the table is dropped. I still have to delete the sequence manually. – Alkanshel Jan 23 '16 at 02:03
  • @Amalgovinus: Then the sequence is not *owned* by the PK column like it would be when created with the `serial` pseudo-type. See: http://stackoverflow.com/a/24659884/939860 or http://stackoverflow.com/a/10002134/939860 and – Erwin Brandstetter Jan 23 '16 at 02:13
  • You're right, my problem was that I was lacking a PK on the sequence field. – Alkanshel Jan 23 '16 at 21:30
  • @Amalgovinus: I am sure I am right, but the PK has nothing to with it. :) The *ownership* is the important piece here. – Erwin Brandstetter Jan 23 '16 at 21:32
  • Just reporting that this problem can happen in Postgres 8.4, but not happened every time for me. Maybe it is a bug, maybe somebody messed up something in my database, I don't know. – Felipe Andrade Oct 07 '16 at 14:40
0

Proceed with caution, "drop sequence sequence_name_here" will successfully drop a sequence even if it's attached as a default nextval() value of a table column. There seems to be some disconnect here especially if the sequence was created separately. I'm also looking for the perfect one liner to clean up 100% unused sequences.

soyayix
  • 175
  • 1
  • 7
0

Building on the answer by @erwin:

DO $$ DECLARE
    r text;
BEGIN
    FOR r IN (
            SELECT cl.relname
            FROM pg_class cl
            LEFT JOIN pg_namespace ns ON ns."oid" = cl.relnamespace
            LEFT JOIN pg_depend d ON d.refobjid = cl."oid" AND d.deptype <> 'i'
            WHERE ns.nspname = 'public' 
                AND cl.relkind = 'S'
                AND d.refobjid IS NULL
        ) LOOP
            -- dangerous, test before you execute!
            RAISE NOTICE '%',  -- once confident, comment this line ...
      --    EXECUTE         -- ... and uncomment this one
                'DROP SEQUENCE ' || quote_ident(r);
    END LOOP;
END $$;

This will actually execute the query and produce the intended result

Emmanuel Mahuni
  • 1,766
  • 16
  • 16
0

If you are using pgAdmin, you can select the sequence and check the "depends on" tab. It will list any object that relies on the sequence.

Another way is to TRY to delete the sequence. If a table references it, pgAdmin will throw an error saying that something is depending on this sequence. If you are able to delete the sequence without any errors, there is no dependency.

Be sure to test this somewhere.

DrColossos
  • 12,656
  • 3
  • 46
  • 67
  • But it is too difficult to drop all sequences one by one manually – user1023877 Nov 25 '11 at 08:55
  • @user1023877 you should than write a script that does something similar to this. You could read the syscatalog to see dependencies, but writing something like this can be tedious as well. Making it short: I don't think there is an easy way for such a task. – DrColossos Nov 25 '11 at 09:11
  • Okay Thank you. could you refer any links which will provide information about how to write script? – user1023877 Nov 25 '11 at 09:50
  • Try the official [docs](http://www.postgresql.org/docs/9.1/static/sql-createfunction.html) and infos for the [system catalog](http://www.postgresql.org/docs/9.1/static/catalogs.html) – DrColossos Nov 25 '11 at 10:02
  • Thank you. I will go through it. – user1023877 Nov 25 '11 at 10:32
0

What i do is first I got all the sequences and then saved these result into a file then i run the file in psql: below content was saved with file name del_seq_all.sql and then list sequences in test1.sql . i dont know this is the correct solution or not. But result is coming as expected.

\o d:/test1.sql
SELECT 'drop sequence ' || c.relname || ';' FROM pg_class c WHERE
(c.relkind = 'S');
\o

\i d:/test1.sql
user1023877
  • 193
  • 2
  • 3
  • 13