列出Postgres db 8.1中的所有序列(sequences)SQL语句为:

211
我正在将数据库从Postgres转换到MySQL。由于找不到可以完成此操作的工具,因此我打算使用autoincrement值在MySQL中将所有Postgres序列转换为自动增量id。
那么,如何使用SQL查询列出Postgres(版本8.1)中所有序列的信息,包括使用它的表、下一个值等?请注意,我无法使用8.4版本中的information_schema.sequences视图。

1
需要注意的是,你正在错误地进行转换。自从Oracle收购Sun以来,他们一直在慢慢扼杀MySQL,因此除非你鄙视你的客户(在这种情况下,你应该简单地辞职),否则你应该坚持使用PostgreSQL,因为没有任何公司(无论是支持垄断还是反对)可以取代PostgreSQL并最终用自己的数据库替换它。 - John
@John 我会说有一亿零一个理由坚持使用Postgres,还有十亿个理由永远不要碰MySQL,但是没错 - 你的观点仍然非常正确 :) - Ruslan
1
@John 在那个时候(2009年),我们需要一个更简单的数据库来处理 - 而且mysql与php更好地配合。 - apelliciari
21个回答

2
上一个回答的改进:

select string_agg('select sequence_name, last_value from ' || relname, chr(13) || 'union' || chr(13) order by relname) 
from pg_class where relkind ='S'

4
请不要只是贴上您的代码而没有任何解释。同时,由于您已经说明了您的代码是“对之前答案的改进”,您也应该告诉我们为什么它是一个改进。加油,欢迎来到SO! - Joel
我应该写一篇毫无意义的文字页面,还是精确的代码(几行)? - Alexander Ryabov
2
从来没有说过那样的话。我喜欢简单、精确的代码。但是,当你声称你的代码是一种改进时,解释一两行为什么它是一种改进(更好的可读性、提高了性能等)不会有坏处。而且你可能也会得到我的赞同。 - Joel

2
select sequence_name, (xpath('/row/last_value/text()', xml_count))[1]::text::int as last_value
from (
    select sequence_schema,
            sequence_name,         
            query_to_xml(format('select last_value from %I.%I', sequence_schema, sequence_name), false, true, '') as xml_count
    from information_schema.sequences
    where sequence_schema = 'public'
) new_table order by last_value desc;

1

部分测试但看起来基本完成。

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;

信用应归于其人... 它部分是从记录有序列的已知表上的 \d 的 SQL 反向工程而来。我相信它也可以更加清洁,但嘿,性能不是一件值得关注的事情。

1
通过解析DEFAULT子句获取每个表的每个列的序列。此方法提供了与哪些列序列链接的信息,并且不使用dependencies,因为某些序列可能不存在。甚至pg_get_serial_sequence(sch.nspname ||'.'|| tbl.relname,col.attname)函数也无法找到所有序列!
解决方案:
SELECT
    seq_sch.nspname  AS sequence_schema
  , seq.relname      AS sequence_name
  , seq_use."schema" AS used_in_schema
  , seq_use."table"  AS used_in_table
  , seq_use."column" AS used_in_column
FROM pg_class seq
  INNER JOIN pg_namespace seq_sch ON seq_sch.oid = seq.relnamespace
  LEFT JOIN (
              SELECT
                  sch.nspname AS "schema"
                , tbl.relname AS "table"
                , col.attname AS "column"
                , regexp_split_to_array(
                      TRIM(LEADING 'nextval(''' FROM
                           TRIM(TRAILING '''::regclass)' FROM
                                pg_get_expr(def.adbin, tbl.oid, TRUE)
                           )
                      )
                      , '\.'
                  )           AS column_sequence
              FROM pg_class tbl --the table
                INNER JOIN pg_namespace sch ON sch.oid = tbl.relnamespace
                --schema
                INNER JOIN pg_attribute col ON col.attrelid = tbl.oid
                --columns
                INNER JOIN pg_attrdef def ON (def.adrelid = tbl.oid AND def.adnum = col.attnum) --default values for columns
              WHERE tbl.relkind = 'r' --regular relations (tables) only
                    AND col.attnum > 0 --regular columns only
                    AND def.adsrc LIKE 'nextval(%)' --sequences only
            ) seq_use ON (seq_use.column_sequence [1] = seq_sch.nspname AND seq_use.column_sequence [2] = seq.relname)
WHERE seq.relkind = 'S' --sequences only
ORDER BY sequence_schema, sequence_name;

请注意,1个序列可以在多个表中使用,因此它可以在这里列出多行。

1

有点像黑客,但可以试试这个:

select 'select ''' || relname  || ''' as sequence, last_value from '  || relname || '  union'
FROM pg_catalog.pg_class c
WHERE c.relkind IN ('S','');

移除最后一个UNION并执行结果


1
感谢您的帮助。
这是一个更新数据库中每个序列的pl/pgsql函数。
---------------------------------------------------------------------------------------------------------
--- Nom : reset_sequence
--- Description : Générique - met à jour les séquences au max de l'identifiant
---------------------------------------------------------------------------------------------------------

CREATE OR REPLACE FUNCTION reset_sequence() RETURNS void AS 
$BODY$
DECLARE _sql VARCHAR := '';
DECLARE result threecol%rowtype; 
BEGIN
FOR result IN 
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,
       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' 
LOOP
     EXECUTE 'SELECT setval('''||result.col1||''', COALESCE((SELECT MAX('||result.col3||')+1 FROM '||result.col2||'), 1), false);';
END LOOP;
END;$BODY$ LANGUAGE plpgsql;

SELECT * FROM reset_sequence();

1
该函数显示每个序列的 last_value。
它输出一个2列表,其中包括序列名称和其最后生成的值。
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();

1

这里是另一个,它在序列名称旁边具有模式名称

select nspname,relname from pg_class c join pg_namespace n on c.relnamespace=n.oid where relkind = 'S' order by nspname

0

这里是一个使用psql获取所有序列及其last_value的列表的示例:

psql -U <username> -d <database> -t -c "SELECT 'SELECT ''' || c.relname || ''' as sequence_name, last_value FROM ' || c.relname || ';' FROM pg_class c WHERE (c.relkind = 'S')" | psql -U <username> -d <database> -t


0
SELECT nextval(sequence_schema || '.' || sequence_name)
FROM information_schema.sequences

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接