Список всех последовательностей в Postgres db 8.1 с SQL

Я конвертирую db из postgres в mysql.

Так как я не могу найти инструмент, который сам выполняет трюк, я собираюсь преобразовать все последовательности postgres в идентификаторы autoincrement в mysql с использованием значения автоинкремента.

Итак, как я могу перечислить все последовательности в Postgres БД (8.1) с информацией о таблице, в которой он использовался, следующее значение и т.д. с SQL запрос?

Помните, что я не могу использовать представление information_schema.sequences в выпуске 8.4.

Ответ 1

Следующий запрос содержит имена всех последовательностей.

SELECT c.relname FROM pg_class c WHERE c.relkind = 'S';

Обычно последовательность называется ${table}_id_seq. Простое сопоставление шаблонов регулярных выражений даст вам имя таблицы.

Чтобы получить последнее значение последовательности, используйте следующий запрос:

SELECT last_value FROM test_id_seq;

Ответ 2

Запуск: psql -E, а затем \ds

Ответ 3

Обратите внимание, что начиная с PostgreSQL 8.4 вы можете получить все информацию о последовательностях, используемых в базе данных, с помощью:

SELECT * FROM information_schema.sequences;

Так как я использую более высокую версию PostgreSQL (9.1) и искал такой же высокий и низкий ответ, я добавил этот ответ для потомков и будущих поисковиков.

Ответ 4

после немного боли, я понял.

лучший способ добиться этого - перечислить все таблицы

select * from pg_tables where schemaname = '<schema_name>'

а затем для каждой таблицы перечислите все столбцы с атрибутами

select * from information_schema.columns where table_name = '<table_name>'

то для каждого столбца проверьте, имеет ли он последовательность

select pg_get_serial_sequence('<table_name>', '<column_name>')

а затем получить информацию об этой последовательности

select * from <sequence_name>

Ответ 5

Связь между автоматически сгенерированными последовательностями (такими как созданные для столбцов SERIAL) и родительская таблица моделируется атрибутом владельца последовательности.

Вы можете изменить это соотношение, используя предложение OWNED BY ALTER SEQUENCE commmand

например.    ALTER SEQUENCE foo_id OWNED от foo_schema.foo_table

чтобы привязать его к таблице foo_table

или    ALTER SEQUENCE foo_id СОБИРАНО NONE

чтобы разбить соединение между последовательностью и любой таблицей

Информация об этой связи сохраняется в таблице каталогов pg_depend.

отношение соединения - это связь между pg_depend.objid → pg_class.oid WHERE relkind = 'S' - которая связывает последовательность с записью объединения, а затем pg_depend.refobjid → pg_class.oid WHERE relkind = 'r', который связывает запись соединения с отношением владельца (таблица)

Этот запрос возвращает все зависимости последовательности → таблицы в базе данных. Предложение where фильтрует его только для включения автоматически сгенерированных отношений, что ограничивает его отображением только последовательностей, созданных столбцами, напечатанными SERIAL.

WITH fq_objects AS (SELECT c.oid,n.nspname || '.' ||c.relname AS fqname , 
                           c.relkind, c.relname AS relation 
                    FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace ),

     sequences AS (SELECT oid,fqname FROM fq_objects WHERE relkind = 'S'),  
     tables    AS (SELECT oid, fqname FROM fq_objects WHERE relkind = 'r' )  
SELECT
       s.fqname AS sequence, 
       '->' as depends, 
       t.fqname AS table 
FROM 
     pg_depend d JOIN sequences s ON s.oid = d.objid  
                 JOIN tables t ON t.oid = d.refobjid  
WHERE 
     d.deptype = 'a' ;

Ответ 6

информация о последовательности: максимальное значение

SELECT * FROM information_schema.sequences;

информация о последовательности: последнее значение

SELECT * FROM <sequence_name>

Ответ 7

Частично проверен, но выглядит в основном полным.

select *
  from (select n.nspname,c.relname,
               (select substring(pg_catalog.pg_get_expr(d.adbin, d.adrelid) for 128)
                  from pg_catalog.pg_attrdef d
                 where d.adrelid=a.attrelid
                   and d.adnum=a.attnum
                   and a.atthasdef) as def
          from pg_class c, pg_attribute a, pg_namespace n
         where c.relkind='r'
           and c.oid=a.attrelid
           and n.oid=c.relnamespace
           and a.atthasdef
           and a.atttypid=20) x
 where x.def ~ '^nextval'
 order by nspname,relname;

Кредит, при котором кредит должен быть... частично отложен из SQL, зарегистрированного из a\d в известной таблице, имеющей последовательность. Я уверен, что это может быть и чище, но эй, производительность не была проблемой.

Ответ 8

Я знаю, что этот пост довольно старый, но я нашел решение CMS очень полезным, поскольку я искал автоматический способ связывания последовательности в столбец AND и хотите поделиться. Использование ключевой таблицы каталога pg_depend. Я расширил то, что было сделано для:

WITH fq_objects AS (SELECT c.oid,n.nspname || '.' ||c.relname AS fqname ,
                           c.relkind, c.relname AS relation
                    FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace ),

     sequences AS (SELECT oid,fqname FROM fq_objects WHERE relkind = 'S'),
     tables    AS (SELECT oid, fqname FROM fq_objects WHERE relkind = 'r' )
SELECT
       s.fqname AS sequence,
       '->' as depends,
       t.fqname AS table,
       a.attname AS column
FROM
     pg_depend d JOIN sequences s ON s.oid = d.objid
                 JOIN tables t ON t.oid = d.refobjid
                 JOIN pg_attribute a ON a.attrelid = d.refobjid and a.attnum = d.refobjsubid
WHERE
     d.deptype = 'a' ;

Эта версия добавляет столбец в список возвращенных полей. Как имя таблицы, так и имя столбца в руке вызов pg_set_serial_sequence позволяет легко убедиться, что все последовательности в базе данных установлены правильно, Например:

CREATE OR REPLACE FUNCTION public.reset_sequence(tablename text, columnname text)
 RETURNS void
 LANGUAGE plpgsql
AS $function$
DECLARE
    _sql VARCHAR := '';
BEGIN
    _sql := $$SELECT setval( pg_get_serial_sequence('$$ || tablename || $$', '$$ || columnname || $$'), (SELECT COALESCE(MAX($$ || columnname || $$),1) FROM $$ || tablename || $$), true)$$;
    EXECUTE _sql;
END;
$function$;

Надеюсь, что это поможет кому-то с повторными настройками!

Ответ 9

Вид взлома, но попробуйте следующее:

выберите 'select' '' || relname || '' 'как последовательность, last_value от' || relname || "союз" FROM pg_catalog.pg_class c WHERE c.relkind IN ('S', '');

Удалите последний СОЮЗ и выполните результат

Ответ 10

Улучшение предыдущего ответа:

select string_agg('select sequence_name, last_value from ' || relname, chr(13) || 'union' || chr(13) order by relname) 
from pg_class where relkind ='S'

Ответ 11

Этот оператор перечисляет таблицу и столбец, связанные с каждой последовательностью:

код:

    SELECT t.relname as related_table, 
           a.attname as related_column,
           s.relname as sequence_name
    FROM pg_class s 
      JOIN pg_depend d ON d.objid = s.oid 
      JOIN pg_class t ON d.objid = s.oid AND d.refobjid = t.oid 
      JOIN pg_attribute a ON (d.refobjid, d.refobjsubid) = (a.attrelid, a.attnum)
      JOIN pg_namespace n ON n.oid = s.relnamespace 
    WHERE s.relkind     = 'S' 

  AND n.nspname     = 'public'

Подробнее см. здесь ссылка для ответа

Ответ 12

Спасибо за вашу помощь.

Вот функция pl/pgsql, которая обновляет каждую последовательность базы данных.

---------------------------------------------------------------------------------------------------------
--- Nom : reset_sequence
--- Description : Générique - met à jour les séquences au max de l'identifiant
---------------------------------------------------------------------------------------------------------

CREATE OR REPLACE FUNCTION reset_sequence() RETURNS void AS 
$BODY$
DECLARE _sql VARCHAR := '';
DECLARE result threecol%rowtype; 
BEGIN
FOR result IN 
WITH fq_objects AS (SELECT c.oid,n.nspname || '.' ||c.relname AS fqname ,c.relkind, c.relname AS relation FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace ),
    sequences AS (SELECT oid,fqname FROM fq_objects WHERE relkind = 'S'),
    tables    AS (SELECT oid, fqname FROM fq_objects WHERE relkind = 'r' )
SELECT
       s.fqname AS sequence,
       t.fqname AS table,
       a.attname AS column
FROM
     pg_depend d JOIN sequences s ON s.oid = d.objid
                 JOIN tables t ON t.oid = d.refobjid
                 JOIN pg_attribute a ON a.attrelid = d.refobjid and a.attnum = d.refobjsubid
WHERE
     d.deptype = 'a' 
LOOP
     EXECUTE 'SELECT setval('''||result.col1||''', COALESCE((SELECT MAX('||result.col3||')+1 FROM '||result.col2||'), 1), false);';
END LOOP;
END;$BODY$ LANGUAGE plpgsql;

SELECT * FROM reset_sequence();

Ответ 13

Вот еще один, который имеет имя схемы рядом с именем последовательности

select nspname,relname from pg_class c join pg_namespace n on c.relnamespace=n.oid where relkind = 'S' order by nspname

Ответ 14

Получать последовательности по каждому столбцу каждой таблицы путем разбора предложения DEFAULT. Этот метод предоставляет информацию о том, какие последовательности столбцов связаны и не использует зависимости, которые могут не существовать для некоторых последовательностей. Даже pg_get_serial_sequence(sch.nspname||'.'||tbl.relname, col.attname) обнаружила не все последовательности для меня!

Решение:

SELECT
    seq_sch.nspname  AS sequence_schema
  , seq.relname      AS sequence_name
  , seq_use."schema" AS used_in_schema
  , seq_use."table"  AS used_in_table
  , seq_use."column" AS used_in_column
FROM pg_class seq
  INNER JOIN pg_namespace seq_sch ON seq_sch.oid = seq.relnamespace
  LEFT JOIN (
              SELECT
                  sch.nspname AS "schema"
                , tbl.relname AS "table"
                , col.attname AS "column"
                , regexp_split_to_array(
                      TRIM(LEADING 'nextval(''' FROM
                           TRIM(TRAILING '''::regclass)' FROM
                                pg_get_expr(def.adbin, tbl.oid, TRUE)
                           )
                      )
                      , '\.'
                  )           AS column_sequence
              FROM pg_class tbl --the table
                INNER JOIN pg_namespace sch ON sch.oid = tbl.relnamespace
                --schema
                INNER JOIN pg_attribute col ON col.attrelid = tbl.oid
                --columns
                INNER JOIN pg_attrdef def ON (def.adrelid = tbl.oid AND def.adnum = col.attnum) --default values for columns
              WHERE tbl.relkind = 'r' --regular relations (tables) only
                    AND col.attnum > 0 --regular columns only
                    AND def.adsrc LIKE 'nextval(%)' --sequences only
            ) seq_use ON (seq_use.column_sequence [1] = seq_sch.nspname AND seq_use.column_sequence [2] = seq.relname)
WHERE seq.relkind = 'S' --sequences only
ORDER BY sequence_schema, sequence_name;

Обратите внимание, что 1 последовательность может использоваться в нескольких таблицах, поэтому она может быть указана в нескольких строках здесь.

Ответ 15

Эта функция показывает последнее значение каждой последовательности.

Он выводит таблицу из двух столбцов, в которой указано имя последовательности плюс ее последнее сгенерированное значение.

drop function if exists public.show_sequence_stats();
CREATE OR REPLACE FUNCTION public.show_sequence_stats()
    RETURNS TABLE(tablename text, last_value bigint) 
    LANGUAGE 'plpgsql'
    COST 100
    VOLATILE 
    ROWS 1000
AS $BODY$
declare r refcursor; rec record; dynamic_query varchar;
        BEGIN
            dynamic_query='select tablename,last_value from (';
            open r for execute 'select nspname,relname from pg_class c join pg_namespace n on c.relnamespace=n.oid where relkind = ''S'' order by nspname'; 
            fetch next from r into rec;
            while found 
            loop
                dynamic_query=dynamic_query || 'select '''|| rec.nspname || '.' || rec.relname ||''' "tablename",last_value from ' || rec.nspname || '.' || rec.relname || ' union all ';
                fetch next from r into rec; 
            end loop;
            close r; 
            dynamic_query=rtrim(dynamic_query,'union all') || ') x order by last_value desc;';
            return query execute dynamic_query;
        END;
$BODY$;

select * from show_sequence_stats();

Ответ 16

Предполагая, что функция exec() объявленная в этом сообщении fooobar.com/info/405220/..., последовательности с их последними значениями могут быть выбраны с использованием одного запроса:

select s.sequence_schema, s.sequence_name,
  (select * from exec('select last_value from ' || s.sequence_schema || '.' || s.sequence_name) as e(lv bigint)) last_value
from information_schema.sequences s