SQL ile Postgres db 8.1'deki tüm dizileri listele


147

Postgres mysql için bir db dönüştürüyorum.

Hile yapan bir araç bulamadığım için, tüm postgres dizilerini autoincrement değeri olan mysql'deki autoincrement id'lerine dönüştüreceğim.

Peki, bir Postgres DB ( 8.1 sürümü) içinde kullanılan tablo, sonraki değer vb bir SQL sorgusu hakkında bilgi ile tüm dizileri nasıl listeleyebilirim ?

information_schema.sequences8.4 sürümünde görünümü kullanamayacağımı unutmayın .


1
Dönüşümü yanlış şekilde yaptığınıza dikkat edilmelidir. Oracle Sun'ı satın aldığından beri yavaş yavaş MySQL'i öldürüyorlar, bu nedenle istemcinizi hor görmedikçe (bu durumda sadece bırakmalısınız) PostgreSQL'e sadık kalmalısınız çünkü hiçbir şirket (tekel yanlısı değil) gelemez, PostgreSQL ve sonunda kendi veritabanı ile değiştirin.
John

@John Ben postgres ile yapışmak için bir milyar ve başka bir neden olduğunu söyleyebilirim ve mysql dokunmak asla bir milyar daha var, ama evet - senin nokta hala çok geçerli :)
Ruslan

@John anda (2009) başa çıkmak için daha basit bir veritabanına ihtiyacımız var - ve mysql daha iyi php
apelliciari ile

Yanıtlar:


251

Aşağıdaki sorgu tüm dizilerin adlarını verir.

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

Genellikle bir dizi olarak adlandırılır ${table}_id_seq. Basit normal ifade desen eşleşmesi size tablo adını verecektir.

Bir dizinin son değerini almak için aşağıdaki sorguyu kullanın:

SELECT last_value FROM test_id_seq;

5
${table}_id_seqİpucu faydalı oldu
Pierre de LESPINAY

${table}_${column}_seqotomatik oluşturulan diziler için
Evgeny Nozdrev

81

PostgreSQL 8.4'ten başlayarak , veritabanında kullanılan diziler hakkında tüm bilgileri aşağıdaki yollarla elde edebileceğinizi unutmayın :

SELECT * FROM information_schema.sequences;

PostgreSQL'in (9.1) daha yüksek bir sürümünü kullandığımdan ve aynı cevabı yüksek ve düşük aradığımdan, bu cevabı gelecek kuşaklara ve gelecekteki araştırmacılar için ekledim.


1
Protip: cevapları "aktif" olarak sıralayın. Sorular gittikçe eski hale geldikçe
gelecek nesiller

1
Güzel. Ve "aktif" sıralama yöntemini seçersem, site ayarı hemen hatırlar (burada boşuna varsayılan olarak ayarlamak için bir yer bulmak için tercihleri ​​araştırıyordum). Hm, şimdi sadece "asker tarafından kabul edilen bir cevap otomatik olarak diğer her şeyi gölgede bırakmazsa" -seçenek, bu gelecek kuşaklar için gerçekten büyük bir zafer olurdu .
SeldomNeedy

Bu tablonun PG
8.4'te

"Tüm bilgiler" mevcut değeri içermez.
bart

62

Çalıştır:, psql -Eve sonra\ds


1
Ben sadece dizi listesine gerek yok, ben kullanılan tablo, sonraki değer vb gerekir .. Ve ben SQL bunu yapmak zorunda
apelliciari

Daha sonra, her sekansta \ d <name> (hala psql -E içinde)

yine, bu SQL'de değil ve dizinin hangi tabloya eklendiğini göstermez
apelliciari

@avastreg: Sana söylediğim gibi mi çalıştırdın? ve neden olmasın?

10
@avastreg: SADECE BİR KEZ YAP . Ve size sorguları gösterecek!

26

biraz acıdan sonra anladım.

bunu başarmanın en iyi yolu tüm tabloları listelemektir

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

ve sonra, her tablo için tüm sütunları niteliklerle listeleyin

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

ardından, her sütun için bir sekansı olup olmadığını test edin

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

ve sonra, bu dizi hakkında bilgi alın

select * from <sequence_name>

13

dizi bilgisi: maksimum değer

SELECT * FROM information_schema.sequences;

dizi bilgisi: son değer

SELECT * FROM <sequence_name>


11

Otomatik olarak oluşturulan diziler (SERİ sütunlar için oluşturulanlar gibi) ve üst tablo arasındaki ilişki, dizi sahibi özniteliği tarafından modellenir.

Bu ilişkiyi, ALTER SEQUENCE komutunun OWNED BY yan tümcesini kullanarak değiştirebilirsiniz.

örneğin ALTER SEQUENCE foo_id OWNED tarafından foo_schema.foo_table

foo_table tablosuna bağlanacak şekilde ayarlamak için

ya da ALTER SEQUENCE foo_id YOK

sekans ve herhangi bir tablo arasındaki bağlantıyı kesmek için

Bu ilişki hakkındaki bilgiler pg_depend katalog tablosunda saklanır .

birleşme ilişkisi, diziyi birleştirme kaydına bağlayan pg_depend.objid -> pg_class.oid WHERE relkind = 'S' - ve sonra bağlantıyı bağlayan pg_depend.refobjid -> pg_class.oid WHERE relkind = 'r' arasındaki bağlantıdır sahip olma ilişkisine kayda katıl (tablo)

Bu sorgu, bir veritabanındaki tüm dizi -> tablo bağımlılıklarını döndürür. Where cümlesi onu yalnızca otomatik olarak oluşturulan ilişkileri içerecek şekilde filtreler, bu da onu yalnızca SERIAL yazılan sütunlar tarafından oluşturulan dizileri görüntülemeyle sınırlar.

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

Tablolar ve sekanslar arasındaki bağımlılıkların yararlı açıklaması. Ama sorgunuz benim için tüm dizileri bulamadı . Bazı dizilerin herhangi bir bağımlılık olmadan var olduğu görülmektedir.
Evgeny Nozdrev

Evet, bu sorgu açıkça yalnızca veritabanı seri sütun tanımlarıyla tanımlanan dizileri göstermektedir. Bu cevapta açıklanmaktadır.
cms

5

Bu yazı oldukça eski olduğunu biliyorum, ama tablo VE sütun bir diziyi bağlamak için otomatik bir yol arıyordum ve paylaşmak istedim CMS çözüm çok yararlı buldum. Pg_depend katalog tablosunun kullanımı anahtardı. Yapıldıkları şeyi genişlettim:

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

Bu sürüm, döndürülen alanlar listesine sütun ekler. Hem tablo adı hem de sütun adı kullanıldığında, pg_set_serial_sequence çağrısı , veritabanındaki tüm sekansların doğru ayarlanmasını sağlamayı kolaylaştırır. Örneğin:

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

Umarım bu dizileri sıfırlayan birine yardımcı olur!


birkaç yıl sonra, güncellemenizi fark ettim ve bir oy vermek için pop
cms

3

Bu ifade, her bir sekansla ilişkili tablo ve sütunu listeler:

Kod:

    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'

daha fazla cevap için buraya bakınız


2

Önceki cevabın geliştirilmesi:

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
Lütfen herhangi bir açıklama yapmadan kodunuzu yazmayın. Ayrıca, kodunuzun "Önceki cevabın iyileştirilmesi" olduğunu belirttiğiniz için, bize bunun neden bir iyileştirme olduğunu da söylemelisiniz. Oh, vazgeçme ve SO'ya hoş geldin!
Joel

Kesin kod (birkaç satır) yerine anlamsız bir metin sayfası yazmalı mıyım?
Alexander Ryabov

2
Bunu asla söylemedim. Basit, kesin kodu severim. Ancak kodunuzun bir iyileştirme olduğunu belirtirken, NEDEN bir iyileştirme (daha iyi okunabilirlik, iyileştirilmiş performans, vb.) Olduğunu açıklayan bir veya iki satır zarar görmez. Muhtemelen benden +1 alırsınız.
Joel

1

Kısmen test edildi, ancak çoğunlukla eksiksiz görünüyor.

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;

Kredi vadesi geldiğinde kredi ... bir dizisi olan bilinen bir tablodaki bir \ d'den kaydedilen SQL'den kısmen tersine mühendislik yapılır. Eminim de daha temiz olabilirdi, ama hey, performans bir endişe değildi.


1

Bir tür hack, ama şunu deneyin:

'seç' '' seçin || relname || '' 'sekans olarak, son_değeri' || relname || 'sendika' FROM pg_catalog.pg_class c NEREDE c.relkind IN ('S', '');

Son BİRLİĞİ kaldırın ve sonucu yürütün


1

DEFAULT yantümcesini ayrıştırarak her tablonun her sütununa göre diziler alın. Bu yöntem, hangi sütun dizilerinin bağlı olduğu hakkında bilgi sağlar ve bazı diziler için mevcut olmayan bağımlılıkları kullanmaz . pg_get_serial_sequence(sch.nspname||'.'||tbl.relname, col.attname)Fonksiyon bile benim için tüm dizileri bulamadı !

Çözüm:

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 dizinin birden çok tabloda kullanılabileceğine dikkat edin, böylece burada birden çok satırda listelenebilir.


0

Yardımınız için teşekkürler.

İşte bir veritabanının her dizisini güncelleyen pl / pgsql işlevi.

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

İşte sıra adının yanında şema adı olan başka bir tane

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

0

Bu işlev, her dizinin son değerini gösterir.

Sıra adını ve son oluşturulan değeri söyleyen 2 sütunlu bir tablo çıkarır.

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

Bu yayında belirtilen exec()işlev https://stackoverflow.com/a/46721603/653539 varsayarsak , son değerleri ile birlikte sekanslar tek bir sorgu kullanılarak getirilebilir:

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

Aşağıda, psqltüm sekansların bir listesini almak için nasıl kullanılacağıyla ilgili bir örnek verilmiştir 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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.