1

データベースには、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);

ただし、[table_name, last_value] または [sequence_name, last_value] のレコードで出力が得られるように、どうにかして各レコードに sequence_name を追加する必要があります。

したがって、関数を次のように呼び出したいと思います。

 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 
4

2 に答える 2

8

あなたの機能はすでにかなり近いようです。次のように少し変更します。

  • シーケンス名をリテラルとして含める
  • 呼び出し元にとって簡単なためではTABLE(...)なく、型指定された列でa を返します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()、他の方法があるかどうかはわかりません)。

于 2013-05-29T18:00:33.470 に答える