【问题标题】:Get max id of all sequences in PostgreSQL获取 PostgreSQL 中所有序列的最大 id
【发布时间】:2013-05-25 00:48:34
【问题描述】:

我们的数据库上有一个监视器来检查接近 max-int 或 max-bigint 的 id。我们刚从 MySQL 搬来,我正在努力在 PostgreSQL 上进行类似的检查。我希望有人可以提供帮助。

这是 MySQL 中的查询

SELECT table_name, auto_increment FROM information_schema.tables WHERE table_schema = DATABASE();

我正在尝试从 PostgreSQL 获得相同的结果。我们找到了一种方法,通过对数据库的大量调用,分别检查每个表。

我只想对数据库进行 1 次调用。到目前为止,这是我所拥有的:

CREATE OR REPLACE FUNCTION getAllSeqId() RETURNS SETOF record AS
$body$
DECLARE
  sequence_name varchar(255);
BEGIN
  FOR sequence_name in SELECT relname FROM pg_class WHERE (relkind = 'S')
  LOOP
      RETURN QUERY EXECUTE 'SELECT last_value FROM ' || sequence_name;
  END LOOP;
  RETURN;
END
$body$
LANGUAGE 'plpgsql';
SELECT last_value from getAllSeqId() as(last_value bigint);

但是,我需要以某种方式将 sequence_name 添加到每条记录中,以便在 [table_name, last_value] 或 [sequence_name, last_value] 的记录中获得输出。

所以我想这样调用我的函数:

 SELECT sequence_name, last_value from getAllSeqId() as(sequence_name varchar(255), last_value bigint);

我该怎么做?

编辑:在 ruby​​ 中,这会创建我们正在寻找的输出。如您所见,我们执行 1 次调用以获取所有索引,然后对每个索引执行 1 次调用以获取最后一个值。必须是更好的方法。

def perform
  find_auto_inc_tables.each do |auto_inc_table|
    check_limit(auto_inc_table, find_curr_auto_inc_id(auto_inc_table))
  end 
end 

def find_curr_auto_inc_id(table_name)
  ActiveRecord::Base.connection.execute("SELECT last_value FROM #{table_name}").first["last_value"].to_i
end 

def find_auto_inc_tables
  ActiveRecord::Base.connection.execute(
    "SELECT c.relname " +
    "FROM pg_class c " +                                                       
    "WHERE c.relkind = 'S'").map { |i| i["relname"] }
end 

【问题讨论】:

  • 哪个版本的 Postgres?

标签: mysql ruby postgresql auto-increment


【解决方案1】:

您的功能似乎已经很接近了。您需要对其进行一些修改:

  • 将序列名称包含为文字
  • 返回带有类型列的 TABLE(...) 而不是 SET OF RECORD,因为它对调用者来说更容易

这是一个修订版:

CREATE OR REPLACE FUNCTION getAllSeqId() RETURNS TABLE(seqname text,val bigint) AS
$body$
DECLARE
  sequence_name varchar(255);
BEGIN
  FOR sequence_name in SELECT relname FROM pg_class WHERE (relkind = 'S')
  LOOP
      RETURN QUERY EXECUTE  'SELECT ' || quote_literal(sequence_name) || '::text,last_value FROM ' || quote_ident(sequence_name);
  END LOOP;
  RETURN;
END
$body$
LANGUAGE 'plpgsql';

请注意,currval() 不是一个选项,因为在同一会话中未设置序列时它会出错(通过调用nextval(),不确定是否有其他方法)。

【讨论】:

  • +1 with quote_ident() for sequence_name 在 from 语句中。
  • 不,这个查询需要quote_literal(),因为它使用序列名称作为文字输出列。如果 quote_ident() 被用作标识符,我们会想要它,例如,如果我们正在构建一个 ALTER SEQUENCE 语句。
  • 是的。我的意思是FROM ' || quote_ident(sequence_name);
  • 像魅力一样工作。谢谢。
  • @Denis:抱歉,我误解了您的第一条评论。 quote_ident 已添加。
【解决方案2】:

像这样简单的东西会起作用吗?

SELECT currval(sequence_name) from information_schema.sequences;

如果你有不是键的序列,我想你可以使用 PG 的序列名称生成模式来尝试限制它。

SELECT currval(sequence_name) from information_schema.sequences
WHERE sequence_name LIKE '%_seq';

如果还是误报太多,可以从 information_schema(或者我不太了解的 pg_* schemata)中获取表名,然后细化 LIKE 参数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-23
    • 2010-10-09
    • 2022-09-22
    • 1970-01-01
    • 1970-01-01
    • 2018-10-06
    • 2016-04-14
    • 2020-11-03
    相关资源
    最近更新 更多