Daftar semua urutan dalam Postgres db 8.1 dengan SQL


147

Saya mengubah db dari postgres ke mysql.

Karena saya tidak dapat menemukan alat yang melakukan triknya sendiri, saya akan mengonversi semua urutan postgres ke id peningkatan otomatis di mysql dengan nilai kenaikan otomatis.

Jadi, bagaimana saya bisa mendaftar semua urutan dalam Postgres DB ( versi 8.1 ) dengan informasi tentang tabel yang digunakannya, nilai selanjutnya dll dengan query SQL?

Ketahuilah bahwa saya tidak dapat menggunakan information_schema.sequencestampilan dalam rilis 8.4.


1
Perlu dicatat bahwa Anda melakukan konversi dengan cara yang salah. Sejak Oracle membeli Sun, mereka perlahan-lahan telah membunuh MySQL, jadi kecuali Anda membenci klien Anda (dalam hal ini Anda harus berhenti), Anda harus tetap menggunakan PostgreSQL karena tidak ada perusahaan (pro-monopoli tidak) yang dapat hadir, melahap PostgreSQL dan akhirnya ganti dengan database mereka sendiri.
Yohanes

@ John Saya akan mengatakan bahwa ada satu miliar dan satu alasan lain untuk bertahan dengan postgres, dan satu miliar lagi untuk tidak pernah menyentuh mysql, tapi ya - poin Anda masih sangat valid :)
Ruslan

@ John pada saat itu (2009) kita membutuhkan database yang lebih sederhana untuk menangani - dan mysql lebih baik digabungkan ke php
apelliciari

Jawaban:


251

Kueri berikut memberikan nama semua urutan.

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

Biasanya urutan disebut sebagai ${table}_id_seq. Pencocokan pola regex sederhana akan memberi Anda nama tabel.

Untuk mendapatkan nilai terakhir dari suatu urutan gunakan permintaan berikut:

SELECT last_value FROM test_id_seq;

5
The ${table}_id_seqpetunjuk berguna
Pierre de LESPINAY

${table}_${column}_sequntuk urutan yang dibuat secara otomatis
Evgeny Nozdrev

81

Perhatikan, bahwa mulai dari PostgreSQL 8.4 Anda bisa mendapatkan semua informasi tentang urutan yang digunakan dalam database melalui:

SELECT * FROM information_schema.sequences;

Karena saya menggunakan versi PostgreSQL (9.1) yang lebih tinggi, dan sedang mencari jawaban yang sama tinggi dan rendah, saya menambahkan jawaban ini demi anak cucu dan untuk pencari masa depan.


1
Protip: urutkan jawaban dengan "aktif". Cucu semakin relevan dengan pertanyaan yang semakin lama semakin tua ..
raveren

1
Keren. Dan sepertinya jika saya memilih metode penyortiran "aktif", situs tersebut langsung mengingat pengaturannya (di sini saya sedang menggali preferensi untuk menemukan tempat untuk menetapkannya sebagai default tetapi tidak berhasil). Hm, sekarang seandainya saja kita memiliki "jawaban yang diterima penanya tidak secara otomatis mengalahkan segala sesuatu yang lain" - itu akan menjadi kemenangan besar bagi anak cucu.
SeldomNeedy

Perhatikan bahwa tabel ini diperkenalkan di PG 8.4, saya lebih suka mengatakan PG 8.2 setelah dokumentasi resmi: postgresql.org/docs/8.2/infoschema-
followingences.html

"Semua informasi" itu tidak termasuk nilai saat ini.
bart

62

Jalankan:, psql -Elalu\ds


1
saya tidak hanya perlu daftar urutan, saya perlu tabel di mana itu digunakan, nilai berikutnya dll. Dan saya harus melakukannya dalam SQL
apelliciari

Kemudian, pada setiap urutan do \ d <name> (masih di psql -E)

lagi, ini bukan di SQL dan tidak menunjukkan di mana meja urutan terpasang
apelliciari

@avastreg: apakah Anda menjalankannya seperti yang saya katakan? dan kenapa tidak?

10
@avastreg: JUST DO IT ONCE . Dan itu akan menunjukkan kepada Anda pertanyaan!

26

Setelah sedikit rasa sakit, saya mendapatkannya.

cara terbaik untuk mencapai ini adalah dengan mendaftar semua tabel

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

dan kemudian, untuk setiap tabel, daftar semua kolom dengan atribut

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

kemudian, untuk setiap kolom, uji apakah memiliki urutan

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

dan kemudian, dapatkan informasi tentang urutan ini

select * from <sequence_name>

13

info urutan: nilai maks

SELECT * FROM information_schema.sequences;

info urutan: nilai terakhir

SELECT * FROM <sequence_name>


11

Hubungan antara urutan yang dibuat secara otomatis (seperti yang dibuat untuk kolom SERIAL) dan tabel induk dimodelkan oleh atribut pemilik urutan.

Anda dapat mengubah hubungan ini menggunakan klausa OWNED BY dari perintah ALTER SEQUENCE

misalnya ALTER SEQUENCE foo_id MILIK oleh foo_schema.foo_table

untuk mengaturnya agar ditautkan ke tabel foo_table

atau ALTER SEQUENCE foo_id MILIK NONE

untuk memutuskan koneksi antara urutan dan tabel apa saja

Informasi tentang hubungan ini disimpan dalam tabel katalog pg_depend .

hubungan bergabung adalah tautan antara pg_depend.objid -> pg_class.oid WHERE relkind = 'S' - yang menghubungkan urutan ke catatan bergabung dan kemudian pg_depend.refobjid -> pg_class.oid WHERE relkind = 'r', yang menghubungkan gabung record ke relasi yang memiliki (tabel)

Kueri ini mengembalikan semua urutan -> dependensi tabel dalam database. Klausa tempat memfilternya hanya menyertakan hubungan yang dibuat secara otomatis, yang membatasi hanya untuk menampilkan urutan yang dibuat oleh kolom yang diketik 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' ;

Penjelasan yang berguna tentang dependensi antara tabel & urutan. Tapi kueri Anda tidak menemukan semua urutan untuk saya. Tampaknya beberapa urutan ada tanpa ada ketergantungan.
Evgeny Nozdrev

ya, kueri ini secara eksplisit hanya menunjukkan urutan yang ditentukan oleh definisi kolom serial database. Ini dijelaskan dalam jawabannya.
cm

5

Saya tahu posting ini cukup lama, tetapi saya menemukan solusi oleh CMS sangat berguna karena saya sedang mencari cara otomatis untuk menautkan urutan ke tabel DAN kolom, dan ingin berbagi. Penggunaan tabel katalog pg_depend adalah kuncinya. Saya memperluas apa yang dilakukan untuk:

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

Versi ini menambahkan kolom ke daftar bidang yang dikembalikan. Dengan kedua nama tabel dan nama kolom di tangan, panggilan ke pg_set_serial_afterence membuatnya mudah untuk memastikan bahwa semua urutan dalam database diatur dengan benar. Sebagai contoh:

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

Semoga ini bisa membantu seseorang dengan mengatur ulang urutan!


beberapa tahun kemudian, saya perhatikan pembaruan Anda, dan mampir untuk memberikan suara positif :-)
cms

3

Pernyataan ini mencantumkan tabel dan kolom yang dikaitkan dengan setiap urutan:

Kode:

    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'

lebih banyak lihat di sini tautan untuk menjawab


2

Peningkatan jawaban sebelumnya:

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
Tolong jangan hanya menaruh kode Anda tanpa penjelasan. Juga, karena Anda telah menyatakan bahwa kode Anda adalah "Peningkatan dari jawaban sebelumnya", Anda juga harus memberi tahu kami MENGAPA itu adalah peningkatan. Oh, jangan menyerah, dan selamat datang di SO!
Joel

Haruskah saya menulis halaman teks yang tidak masuk akal alih-alih kode yang tepat (beberapa baris)?
Alexander Ryabov

2
Tidak pernah mengatakan itu. Saya suka kode yang sederhana dan tepat. Tetapi ketika menyatakan bahwa kode Anda merupakan peningkatan, satu atau dua baris yang menjelaskan MENGAPA itu merupakan peningkatan (keterbacaan yang lebih baik, peningkatan kinerja, dll) tidak akan ada salahnya. Dan Anda mungkin akan mendapatkan +1 dari saya juga.
Joel

1

Diuji sebagian tetapi sebagian besar terlihat lengkap.

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;

Kredit di mana kredit jatuh tempo ... sebagian direkayasa balik dari SQL yang dicatat dari a pada tabel yang diketahui yang memiliki urutan. Saya yakin itu bisa lebih bersih juga, tapi hei, kinerja bukan masalah.


1

Jenis peretasan, tetapi coba ini:

pilih 'pilih' '' || relname || '' 'sebagai urutan, last_value dari' || relname || 'union' FROM pg_catalog.pg_class c WHERE c.relkind IN ('S', '');

Hapus UNION terakhir dan jalankan hasilnya


1

Dapatkan urutan dengan setiap kolom dari setiap tabel melalui penguraian klausa DEFAULT. Metode ini memberikan info tentang urutan kolom mana yang ditautkan dan tidak menggunakan dependensi yang mungkin tidak ada untuk beberapa urutan. Bahkan pg_get_serial_sequence(sch.nspname||'.'||tbl.relname, col.attname)fungsi menemukan tidak semua urutan untuk saya!

Larutan:

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;

Perhatikan bahwa 1 urutan dapat digunakan dalam beberapa tabel, sehingga dapat dicantumkan dalam beberapa baris di sini.


0

Terima kasih atas bantuan Anda.

Berikut adalah fungsi pl / pgsql yang memperbarui setiap urutan basis data.

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

Berikut ini adalah satu lagi yang memiliki nama skema di sebelah nama urutan

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

0

Fungsi ini menunjukkan nilai terakhir dari setiap urutan.

Ini menghasilkan tabel 2 kolom yang mengatakan nama urutan ditambah nilai yang terakhir dihasilkan.

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

Dengan asumsi exec()fungsi yang dideklarasikan dalam posting ini https://stackoverflow.com/a/46721603/653539 , urutan bersama dengan nilai terakhirnya dapat diambil menggunakan kueri tunggal:

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

Berikut adalah contoh cara menggunakan psqluntuk mendapatkan daftar semua urutan dengan 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

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.