列出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个回答

347
以下查询返回所有序列的名称。
SELECT c.relname FROM pg_class c WHERE c.relkind = 'S' order BY c.relname;

通常,一个序列被命名为${table}_id_seq。简单的正则表达式模式匹配将给出表名。
要获取序列的最后一个值,请使用以下查询:
SELECT last_value FROM test_id_seq;

10
${table}_id_seq 提示很有用。 - Pierre de LESPINAY
3
${table}_${column}_seq表示自动生成的序列。 - Evgeny Nozdrev

133

请注意,从PostgreSQL 8.4开始,您可以通过以下方式获取数据库中使用的所有序列的信息:

SELECT * FROM information_schema.sequences;

由于我正在使用较高版本的PostgreSQL(9.1),并且一直在寻找相同的答案,因此我为了后人和未来的搜索者添加了这个答案。


1
专业提示:按“活跃”排序答案。随着问题变得越来越老,后人获得的信息会变得越来越相关。 - raveren
1
很好。如果我选择“活跃”排序方法,网站似乎会立即记住设置(在这里,我正在偏好设置中寻找将其设置为默认值的地方,但没有找到)。嗯,现在如果我们有一个“提问者接受的答案不会自动压倒其他所有选项”的选项,那将是对后人真正伟大的胜利。 - Seldom 'Where's Monica' Needy
不确定这个表是在PG 8.4中引入的,我更倾向于说官方文档中的PG 8.2:https://www.postgresql.org/docs/8.2/infoschema-sequences.html - Guillaume Husta
“所有信息”并不包括当前值。 - bart
1
是的,你仍然需要使用 SELECT last_value FROM <sequence_name> 来获取它。这个答案展示了序列的模式,这正是我需要过滤的内容,而且在 pg_class 视图中是不可用的。 - GameSalutes

74

使用-E标志(“回显由\d和其他反斜杠命令生成的实际查询”)启动psql,然后输入\ds命令以列出所有序列。您应该会看到类似于以下内容:

# \ds
********* QUERY **********
SELECT n.nspname as "Schema",
  c.relname as "Name",
  CASE c.relkind WHEN 'r' THEN 'table' WHEN 'v' THEN 'view' WHEN 'm' THEN 'materialized view' WHEN 'i' THEN 'index' WHEN 'S' THEN 'sequence' WHEN 's' THEN 'special' WHEN 'f' THEN 'foreign table' WHEN 'p' THEN 'partitioned table' WHEN 'I' THEN 'partitioned index' END as "Type",
  pg_catalog.pg_get_userbyid(c.relowner) as "Owner"
FROM pg_catalog.pg_class c
     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind IN ('S','')
      AND n.nspname <> 'pg_catalog'
      AND n.nspname <> 'information_schema'
      AND n.nspname !~ '^pg_toast'
  AND pg_catalog.pg_table_is_visible(c.oid)
ORDER BY 1,2;
**************************

                     List of relations
 Schema |              Name              |   Type   | Owner 
--------+--------------------------------+----------+-------
 public | assignments_id_seq             | sequence | root
 public | framework_users_id_seq         | sequence | root
 public | lending_items_id_seq           | sequence | root
 public | proxy_borrower_requests_id_seq | sequence | root
 public | roles_id_seq                   | sequence | root
 public | stack_requests_id_seq          | sequence | root
(6 rows)

要检查特定的序列,您可以运行\d <序列名称>

# \d lending_items_id_seq
********* QUERY **********

(...about four queries...)

**************************

                    Sequence "public.lending_items_id_seq"
  Type  | Start | Minimum |       Maximum       | Increment | Cycles? | Cache 
--------+-------+---------+---------------------+-----------+---------+-------
 bigint |     1 |       1 | 9223372036854775807 |         1 | no      |     1
Owned by: public.lending_items.id

1
我不仅需要序列列表,还需要使用它的表格、下一个值等等……而且我必须在SQL中完成这个任务。 - apelliciari
@avastreg:看起来你没有尝试建议,因为它会向你展示你所需的确切 SQL。 - user330315
我需要直接使用SQL语句来完成这个任务!我不能使用命令行。 - apelliciari
11
只需要执行一次,它就会显示你的查询!请执行@avastreg中提到的操作。 - user80168
抱歉,现在我才明白你的意思! - apelliciari
显示剩余3条评论

36

经过一番努力,我终于明白了。

实现这个目标的最好方法是列出所有的表格。

select * from pg_tables where schemaname = '<schema_name>'

然后,针对每个表格,列出所有具有属性的列

select * from information_schema.columns where table_name = '<table_name>'

然后,对于每一列,测试它是否有序列。

select pg_get_serial_sequence('<table_name>', '<column_name>')

然后,获取有关该序列的信息。

select * from <sequence_name>

18

序列信息:最大值

SELECT * FROM information_schema.sequences;

序列信息:上次值

SELECT * FROM <sequence_name>


13

获取所有序列:

select * from pg_sequences;

PSQL:

\ds
\ds+
\ds *actor*
\ds *actor*将获取所有序列名称中包含actor字符的序列。

12
自动生成的序列(例如为SERIAL列创建的序列)与父表之间的关系由序列所有者属性进行建模。
您可以使用ALTER SEQUENCE命令的OWNED BY子句来修改此关系。
例如,ALTER SEQUENCE foo_id OWNED by foo_schema.foo_table,将其设置为链接到表foo_table。
或者 ALTER SEQUENCE foo_id OWNED by NONE,以断开序列与任何表之间的连接。
有关此关系的信息存储在pg_depend目录表中。
连接关系是pg_depend.objid -> pg_class.oid WHERE relkind ='S'的链接记录和pg_depend.refobjid -> pg_class.oid WHERE relkind ='r'的连接记录之间的链接,这将链接序列到连接记录,然后链接连接记录到拥有关系(表)。
此查询返回数据库中所有序列到表的依赖关系。where子句将其过滤,仅包括自动生成的关系,这限制了它仅显示由SERIAL类型列创建的序列。
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' ;

有关表和序列之间依赖关系的解释很有用。但是你的查询对我来说没有找到所有序列。似乎存在一些没有任何依赖关系的序列。 - Evgeny Nozdrev
是的,此查询明确地仅演示由数据库序列列定义定义的序列。这在答案中有解释。 - cms

8

我知道这篇文章很旧了,但是我发现CMS的解决方案非常有用,因为我正在寻找一种自动将序列链接到表和列的方法,并想分享。使用pg_depend目录表是关键。我扩展了所做的事情:

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' ;

此版本添加了列到返回字段列表中。通过表名和列名,可以轻松调用pg_set_serial_sequence来确保数据库中所有序列都被正确设置。例如:

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$;

希望这能帮助有需要的人重置序列!

几年过去了,我注意到你的更新,并且来给你点赞 :-) - cms
1
感谢 @cms。我今天仍在使用它。 - DBAYoder

8

我知道这个问题是关于PostgreSQL 8版本的,但我在这里写了一个简单的方法,供想要获得版本10及以上序列的人使用

您可以使用以下查询

select * from pg_sequences

查看pg序列


4
此语句列出了每个序列相关的表和列:
代码:
    SELECT t.relname as related_table, 
           a.attname as related_column,
           s.relname as sequence_name
    FROM pg_class s 
      JOIN pg_depend d ON d.objid = s.oid 
      JOIN pg_class t ON d.objid = s.oid AND d.refobjid = t.oid 
      JOIN pg_attribute a ON (d.refobjid, d.refobjsubid) = (a.attrelid, a.attnum)
      JOIN pg_namespace n ON n.oid = s.relnamespace 
    WHERE s.relkind     = 'S' 

  AND n.nspname     = 'public'

更多见此处答案链接


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