获取PostgreSQL中所有序列的最大ID

时间:2013-05-29 16:28:36

标签: mysql ruby postgresql auto-increment

我们的数据库上有一个监视器,用于检查接近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 

2 个答案:

答案 0 :(得分:7)

你的功能似乎已经非常接近了。你想稍微修改一下:

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

以下是修订版:

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(),不确定是否有其他方式)。

答案 1 :(得分:0)

这样的工作会简单吗?

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参数。