Перерахуйте всі послідовності в Postgres db 8.1 з SQL


147

Я перетворюю db з postgres в mysql.

Оскільки я не можу знайти інструмент, який виконує трюк сам, я збираюся перетворити всі послідовності постгресів до ідентифікаторів автопосилення в mysql зі значенням автоматичного збільшення.

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

Будьте в курсі, що я не можу використовувати information_schema.sequencesпредставлення у випуску 8.4.


1
Слід зазначити, що ви робите конверсію неправильно. Оскільки Oracle купив Sun, вони потихеньку вбивають MySQL, тому, якщо ви не зневажаєте свого клієнта (у такому випадку вам слід просто вийти), вам слід дотримуватися PostgreSQL, оскільки жодна корпорація (промонополія не може) прийти разом, збивати PostgreSQL і врешті-решт замініть його власною базою даних.
Іван

@John Я б сказав, що є мільярд і ще одна причина, щоб дотримуватися постгресів, і мільярд більше, щоб ніколи не торкатися mysql, але так - ваш пункт все ще дуже дійсний :)
Руслан,

@John на той час (2009 р.) Нам потрібна простіша база даних для вирішення - і mysql був краще поєднаний з php
apelliciari

Відповіді:


250

Наступний запит дає назви всіх послідовностей.

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

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

Щоб отримати останнє значення послідовності, використовуйте наступний запит:

SELECT last_value FROM test_id_seq;

5
${table}_id_seqНатяк був корисний
П'єр де LESPINAY

${table}_${column}_seqдля автоматично створених послідовностей
Євген Ноздрев

80

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

SELECT * FROM information_schema.sequences;

Оскільки я використовую більш високу версію PostgreSQL (9.1) і шукав однакові відповіді високо і низько, я додав цю відповідь заради нащадків та для майбутніх пошукових працівників.


1
Підказка: сортуйте відповіді за "активним". Потомство стає все більш актуальним, оскільки питання стають
старішими

1
Класно. І виглядає так, що якщо я вибираю "активний" метод сортування, сайт відразу запам'ятовує налаштування (тут я копався в налаштуваннях, щоб знайти місце, щоб встановити його за замовчуванням безрезультатно). Гм, тепер, якби тільки у нас була відповідь "прийнята запитувачем відповідь не автоматично козир про все інше" - це було б справді великою перемогою для нащадків.
SeldomNeedy

Зауважте, що ця таблиця була введена в PG 8.4, я б сказала, що це PG 8.2 після офіційної документації: postgresql.org/docs/8.2/infoschema-sequences.html
Гійом Хуста

Ця "вся інформація" не включає поточне значення.
Барт

62

Виконати:, psql -Eа потім\ds


1
мені не потрібен лише список послідовностей, мені потрібна таблиця, в якій він використовується, наступне значення тощо. І мені це потрібно зробити в SQL
apelliciari

Потім у кожній послідовності виконайте \ d <ім'я> (перебуваючи досі в psql -E)

знову ж таки, це не в SQL і не показує, за якою таблицею додається послідовність
apelliciari

@avastreg: ти запустив це так, як я тобі сказав? а чому ні?

10
@avastreg: JUST DO IT РАЗ . І він покаже вам запити!

26

після трохи болю я отримав це.

найкращий спосіб досягти цього - перерахувати всі таблиці

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>

13

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

SELECT * FROM information_schema.sequences;

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

SELECT * FROM <sequence_name>


11

Зв'язок між автоматично сформованими послідовностями (такими, які створені для стовпців СЕРІАН) та батьківською таблицею моделюється атрибутом власника послідовностей.

Ви можете змінити це відношення за допомогою пункту OWNED BY в команді ALTER SEQUENCE

напр., ПІСЛЯ СЕКЦІОННОСТІ foo_id ВЛАСНИЙ foo_schema.foo_table

щоб встановити, щоб він був пов'язаний з таблицею foo_table

або АЛЕ ПОСЛІДНОСТІ foo_id ВЛАСНІЙ НІКОЛИ

щоб перервати зв’язок між послідовністю та будь-якою таблицею

Інформація про цей взаємозв'язок зберігається в таблиці каталогу pg_depend .

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

Цей запит повертає всі залежності послідовності -> таблиці в базі даних. Пункт де фільтрує його, включаючи лише автоматичні згенеровані відносини, що обмежує його лише відображенням послідовностей, створених стовпцями типу 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' ;

Корисне пояснення залежності між таблицями та послідовностями. Але ваш запит знайшов не всі послідовності для мене. Здається, деякі послідовності існують без будь-яких залежностей.
Євгеній Ноздрев

так, цей запит явно демонструє лише послідовності, визначені визначеннями послідовних стовпців бази даних. Це пояснено у відповіді.
cms

5

Я знаю, що ця публікація досить стара, але я знайшов рішення CMS дуже корисним, оскільки шукав автоматизований спосіб прив’язати послідовність до таблиці І стовпця, і хотів поділитися. Ключовим було використання таблиці 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$;

Сподіваюся, це допомагає комусь із скиданням послідовностей!


через декілька років я помічаю ваше оновлення, і я попросив вас підняти підсумки :-)
cms

3

Це твердження перераховує таблицю та стовпець, пов’язані з кожною послідовністю:

Код:

    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'

більше дивіться тут посилання для відповіді


2

Удосконалення попередньої відповіді:

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

3
Будь ласка, не проставляйте свій код без будь-яких пояснень. Крім того, оскільки ви заявили, що ваш код є "Поліпшенням попередньої відповіді", ви також повинні сказати, ЧОМУ це поліпшення. О, не здавайся, і ласкаво просимо до ТА!
Джоель

Чи слід писати сторінку безглуздого тексту замість точного коду (пара рядків)?
Олександр Рябов

2
Ніколи цього не говорив. Мені подобається простий, точний код. Але якщо заявити, що ваш код є вдосконаленням, один чи два рядки, що пояснюють, ЧОМУ це поліпшення (краща читабельність, покращена продуктивність тощо), не зашкодить. І ви, мабуть, отримаєте +1 і від мене.
Джоель

1

Частково перевірено, але виглядає переважно повною.

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 з \ d на відомій таблиці, що мала послідовність. Я впевнений, що це може бути і чистішим, але так, ефективність не викликала проблем.


1

Вид хаку, але спробуйте це:

виберіть 'select' '' || перейменування || '' 'як послідовність, last_value від' || перейменування || 'об'єднання' ВІД pg_catalog.pg_class c WHERE c.relkind IN ('S', '');

Видаліть останній UNION і виконайте результат


1

Отримуйте послідовності в кожному стовпчику кожної таблиці за допомогою аналізу 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 послідовність може бути використана в декількох таблицях, тому вона може бути перерахована тут у кількох рядках.


0

Спасибі за вашу допомогу.

Ось функція 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();

0

Ось ще одна, яка має назву схеми поруч із іменем послідовності

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

0

Ця функція показує останнє значення кожної послідовності.

Він виводить таблицю з 2 стовпцями, в якій зазначено ім'я послідовності плюс його останнє генероване значення.

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

0

Припустимо, що exec()функція, оголошена в цьому дописі https://stackoverflow.com/a/46721603/653539 , послідовності разом з останніми значеннями можна отримати за допомогою одного запиту:

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

0
select sequence_name, (xpath('/row/last_value/text()', xml_count))[1]::text::int as last_value
from (
    select sequence_schema,
            sequence_name,         
            query_to_xml(format('select last_value from %I.%I', sequence_schema, sequence_name), false, true, '') as xml_count
    from information_schema.sequences
    where sequence_schema = 'public'
) new_table order by last_value desc;

0

Ось приклад, як використовувати psqlдля отримання списку всіх послідовностей з їхніми last_value:

psql -U <username> -d <database> -t -c "SELECT 'SELECT ''' || c.relname || ''' as sequence_name, last_value FROM ' || c.relname || ';' FROM pg_class c WHERE (c.relkind = 'S')" | psql -U <username> -d <database> -t

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.