2013-05-29 37 views
0

我们在我们的数据库中有一个监视器来检查接近max-int或max-bigint的id。我们刚刚从MySQL迁移而来,并且很努力地在PostgreSQL上获得类似的检查。我希望有人能帮忙。获取PostgreSQL中所有序列的最大ID

这里的查询在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某种方式添加到每个记录,使我在[表名,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 
+0

哪个版本的Postgres? –

+0

Postgres版本9.2 –

回答

5

你的功能已经很接近了。你想修改它有点:

  • 包括序列名称为文字
  • 返回一个类型化的列,而不是SET OF RECORD一个TABLE(...)因为它是呼叫者

这里更容易是一个修订版本:

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()不是一个选项,因为当序列没有蜂时它错误n在同一会话中设置(通过调用nextval(),不确定是否有其他方式)。

+0

带''quote_ident()'在from语句中用于'sequence_name'。 –

+0

不是它真的是'quote_literal()',因为它使用序列名称作为文字输出列,所以在这个查询中是需要的。我们希望'quote_ident()'如果它被用作标识符,例如,如果我们正在构建一个ALTER SEQUENCE语句。 –

+0

是的。我的意思是'从'|| quote_ident(sequence_name);' –

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_ *图式,我不很清楚),表名和完善LIKE参数。