List all sequences in a Postgres db 8.1 with SQL

后端 未结 19 1709
旧时难觅i
旧时难觅i 2020-12-12 11:30

I\'m converting a db from postgres to mysql.

Since i cannot find a tool that does the trick itself, i\'m going to convert all postgres sequences to autoincrement id

相关标签:
19条回答
  • 2020-12-12 11:54

    I know this post is pretty old, but I found the solution by CMS to be very useful as I was looking for an automated way to link a sequence to the table AND column, and wanted to share. The use of pg_depend catalog table was the key. I expanded what was done to:

    WITH fq_objects AS (SELECT c.oid,n.nspname || '.' ||c.relname AS fqname ,
                               c.relkind, c.relname AS relation
                        FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace ),
    
         sequences AS (SELECT oid,fqname FROM fq_objects WHERE relkind = 'S'),
         tables    AS (SELECT oid, fqname FROM fq_objects WHERE relkind = 'r' )
    SELECT
           s.fqname AS sequence,
           '->' as depends,
           t.fqname AS table,
           a.attname AS column
    FROM
         pg_depend d JOIN sequences s ON s.oid = d.objid
                     JOIN tables t ON t.oid = d.refobjid
                     JOIN pg_attribute a ON a.attrelid = d.refobjid and a.attnum = d.refobjsubid
    WHERE
         d.deptype = 'a' ;
    

    This version adds column to the list of fields returned. With both the table name and the column name in hand, a call to pg_set_serial_sequence makes it easy to ensure that all sequences in the database are set correctly. For example:

    CREATE OR REPLACE FUNCTION public.reset_sequence(tablename text, columnname text)
     RETURNS void
     LANGUAGE plpgsql
    AS $function$
    DECLARE
        _sql VARCHAR := '';
    BEGIN
        _sql := $$SELECT setval( pg_get_serial_sequence('$$ || tablename || $$', '$$ || columnname || $$'), (SELECT COALESCE(MAX($$ || columnname || $$),1) FROM $$ || tablename || $$), true)$$;
        EXECUTE _sql;
    END;
    $function$;
    

    Hope this helps someone with resetting sequences!

    0 讨论(0)
  • 2020-12-12 11:56

    Assuming exec() function declared in this post https://stackoverflow.com/a/46721603/653539 , sequences together with their last values can be fetched using single query:

    select s.sequence_schema, s.sequence_name,
      (select * from exec('select last_value from ' || s.sequence_schema || '.' || s.sequence_name) as e(lv bigint)) last_value
    from information_schema.sequences s
    
    0 讨论(0)
  • 2020-12-12 11:57

    This function shows the last_value of each sequence.

    It outputs a 2 columns table that says the sequence name plus it's last generated value.

    drop function if exists public.show_sequence_stats();
    CREATE OR REPLACE FUNCTION public.show_sequence_stats()
        RETURNS TABLE(tablename text, last_value bigint) 
        LANGUAGE 'plpgsql'
        COST 100
        VOLATILE 
        ROWS 1000
    AS $BODY$
    declare r refcursor; rec record; dynamic_query varchar;
            BEGIN
                dynamic_query='select tablename,last_value from (';
                open r for execute 'select nspname,relname from pg_class c join pg_namespace n on c.relnamespace=n.oid where relkind = ''S'' order by nspname'; 
                fetch next from r into rec;
                while found 
                loop
                    dynamic_query=dynamic_query || 'select '''|| rec.nspname || '.' || rec.relname ||''' "tablename",last_value from ' || rec.nspname || '.' || rec.relname || ' union all ';
                    fetch next from r into rec; 
                end loop;
                close r; 
                dynamic_query=rtrim(dynamic_query,'union all') || ') x order by last_value desc;';
                return query execute dynamic_query;
            END;
    $BODY$;
    
    select * from show_sequence_stats();
    
    0 讨论(0)
  • 2020-12-12 11:59

    Partially tested but looks mostly complete.

    select *
      from (select n.nspname,c.relname,
                   (select substring(pg_catalog.pg_get_expr(d.adbin, d.adrelid) for 128)
                      from pg_catalog.pg_attrdef d
                     where d.adrelid=a.attrelid
                       and d.adnum=a.attnum
                       and a.atthasdef) as def
              from pg_class c, pg_attribute a, pg_namespace n
             where c.relkind='r'
               and c.oid=a.attrelid
               and n.oid=c.relnamespace
               and a.atthasdef
               and a.atttypid=20) x
     where x.def ~ '^nextval'
     order by nspname,relname;
    

    Credit where credit is due... it's partly reverse engineered from the SQL logged from a \d on a known table that had a sequence. I'm sure it could be cleaner too, but hey, performance wasn't a concern.

    0 讨论(0)
  • 2020-12-12 12:01

    The relationship between automatically generated sequences ( such as those created for SERIAL columns ) and the parent table is modelled by the sequence owner attribute.

    You can modify this relationship using the OWNED BY clause of the ALTER SEQUENCE commmand

    e.g. ALTER SEQUENCE foo_id OWNED by foo_schema.foo_table

    to set it to be linked to the table foo_table

    or ALTER SEQUENCE foo_id OWNED by NONE

    to break the connection between the sequence and any table

    The information about this relationship is stored in the pg_depend catalogue table.

    the joining relationship is the link between pg_depend.objid -> pg_class.oid WHERE relkind = 'S' - which links the sequence to the join record and then pg_depend.refobjid -> pg_class.oid WHERE relkind = 'r' , which links the join record to the owning relation ( table )

    This query returns all the sequence -> table dependencies in a database. The where clause filters it to only include auto generated relationships, which restricts it to only display sequences created by SERIAL typed columns.

    WITH fq_objects AS (SELECT c.oid,n.nspname || '.' ||c.relname AS fqname , 
                               c.relkind, c.relname AS relation 
                        FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace ),
    
         sequences AS (SELECT oid,fqname FROM fq_objects WHERE relkind = 'S'),  
         tables    AS (SELECT oid, fqname FROM fq_objects WHERE relkind = 'r' )  
    SELECT
           s.fqname AS sequence, 
           '->' as depends, 
           t.fqname AS table 
    FROM 
         pg_depend d JOIN sequences s ON s.oid = d.objid  
                     JOIN tables t ON t.oid = d.refobjid  
    WHERE 
         d.deptype = 'a' ;
    
    0 讨论(0)
  • 2020-12-12 12:02

    sequence info : max value

    SELECT * FROM information_schema.sequences;

    sequence info : last value

    SELECT * FROM <sequence_name>

    0 讨论(0)
提交回复
热议问题