Атрымаць максімальны ідэнтыфікатар ўсіх паслядоўнасцяў у PostgreSQL

У нас ёсць манітор на нашых базах дадзеных для праверкі ідэнтыфікатараў надыходзячых макс-ИНТ або макс-BIGINT. Мы толькі што пераехалі з MySQL, і я з усіх сіл, каб атрымаць падобны чэк, які працуе на PostgreSQL. Я спадзяюся, што хто-то можа дапамагчы.

Вось запыт у MySQL

<�Код> ВЫБАР имя_таблица, auto_increment АД INFORMATION_SCHEMA.TABLES ГДЕ table_schema = БАЗА ДАНЫХ ();

Я спрабую атрымаць тыя ж вынікі з PostgreSQL. Мы знайшлі спосаб зрабіць гэта з кучай званкоў у базу дадзеных, правяраючы кожную табліцу паасобку.

Я хацеў бы зрабіць толькі адзін званок у базу дадзеных. Вось тое, што я да гэтага часу:

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);

Як я магу гэта зрабіць?

EDIT: In ruby, this creates the output we're looking for. As you can see, we're doing 1 call to get all the indexes, then 1 call per index to get the last value. Gotta be a better way.

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 версія 9.2
дададзена аўтар John Hinnegan, крыніца
Postgres версія 9.2
дададзена аўтар John Hinnegan, крыніца
Postgres версія 9.2
дададзена аўтар John Hinnegan, крыніца
Якая версія Postgres?
дададзена аўтар Andrew Lazarus, крыніца
Якая версія Postgres?
дададзена аўтар Andrew Lazarus, крыніца

6 адказы

Ваша функцыя, здаецца, зусім блізка ўжо. Вы хацелі б змяніць яго трохі, каб:

  • ўключаюць імёны паслядоўнасцяў як литералы
  • вяртае 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() , не ўпэўнены, калі ёсць якая-небудзь іншы спосаб).

5
дададзена
Працуе як шарм. Дзякуючы.
дададзена аўтар John Hinnegan, крыніца
Так. Я меў на ўвазе FROM '|| quote_ident (sequence_name);
дададзена аўтар Denis de Bernardy, крыніца
+1 з quote_ident() для sequence_name у з заявай.
дададзена аўтар Denis de Bernardy, крыніца
@Denis: шкада, што я няправільна вытлумачыў свой першы каментар. <�Код> quote_ident дададзены.
дададзена аўтар Daniel Vérité, крыніца
Не, гэта сапраўды quote_literal() , які неабходны ў гэтым запыце, паколькі ён выкарыстоўвае імя паслядоўнасці ў літаральным выходным Стоўбцах. Мы хацелі quote_ident() , калі ён быў выкарыстаны ў якасці ідэнтыфікатара, напрыклад, калі мы будуем аператар SEQUENCE ALTER.
дададзена аўтар Daniel Vérité, крыніца

Ваша функцыя, здаецца, зусім блізка ўжо. Вы хацелі б змяніць яго трохі, каб:

  • ўключаюць імёны паслядоўнасцяў як литералы
  • вяртае 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() , не ўпэўнены, калі ёсць якая-небудзь іншы спосаб).

5
дададзена
Працуе як шарм. Дзякуючы.
дададзена аўтар John Hinnegan, крыніца
Так. Я меў на ўвазе FROM '|| quote_ident (sequence_name);
дададзена аўтар Denis de Bernardy, крыніца
+1 з quote_ident() для sequence_name у з заявай.
дададзена аўтар Denis de Bernardy, крыніца
@Denis: шкада, што я няправільна вытлумачыў свой першы каментар. <�Код> quote_ident дададзены.
дададзена аўтар Daniel Vérité, крыніца
Не, гэта сапраўды quote_literal() , які неабходны ў гэтым запыце, паколькі ён выкарыстоўвае імя паслядоўнасці ў літаральным выходным Стоўбцах. Мы хацелі quote_ident() , калі ён быў выкарыстаны ў якасці ідэнтыфікатара, напрыклад, калі мы будуем аператар SEQUENCE ALTER.
дададзена аўтар Daniel Vérité, крыніца

Ваша функцыя, здаецца, зусім блізка ўжо. Вы хацелі б змяніць яго трохі, каб:

  • ўключаюць імёны паслядоўнасцяў як литералы
  • вяртае 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() , не ўпэўнены, калі ёсць якая-небудзь іншы спосаб).

5
дададзена
Працуе як шарм. Дзякуючы.
дададзена аўтар John Hinnegan, крыніца
+1 з quote_ident() для sequence_name у з заявай.
дададзена аўтар Denis de Bernardy, крыніца
Так. Я меў на ўвазе FROM '|| quote_ident (sequence_name);
дададзена аўтар Denis de Bernardy, крыніца
@Denis: шкада, што я няправільна вытлумачыў свой першы каментар. <�Код> quote_ident дададзены.
дададзена аўтар Daniel Vérité, крыніца
Не, гэта сапраўды quote_literal() , які неабходны ў гэтым запыце, паколькі ён выкарыстоўвае імя паслядоўнасці ў літаральным выходным Стоўбцах. Мы хацелі quote_ident() , калі ён быў выкарыстаны ў якасці ідэнтыфікатара, напрыклад, калі мы будуем аператар SEQUENCE ALTER.
дададзена аўтар Daniel Vérité, крыніца

Ці будзе што-то так проста, як гэты твор?

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 параметру.

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 параметру.

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 параметру.

0
дададзена