2013-05-29 35 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參數。