2009-09-29 34 views
82

Konwertuję db z postgres na mysql.Lista wszystkich sekwencji w Postgres db 8.1 z SQL

Ponieważ nie mogę znaleźć narzędzia, które sam się podoba, zamierzam przekonwertować wszystkie sekwencje postgresów na autoinrement ids w mysql z wartością autoinkrementacji.

Więc jak mogę wymienić wszystkich sekwencji w Postgres DB (8,1 wersja) informacje o tabeli, w której jest używany, etc następnej wartości z kwerendy SQL?

Należy pamiętać, że nie można użyć widoku information_schema.sequences w wydaniu 8.4.

+1

Należy zauważyć, że dokonujesz konwersji w niewłaściwy sposób. Odkąd Oracle kupił Sun, powoli zabijają MySQL, więc jeśli nie gardzisz swoim klientem (w takim przypadku powinieneś po prostu zrezygnować) powinieneś trzymać się PostgreSQL, ponieważ żadna korporacja (pro-monopol na nie) nie może nadejść, pożerać PostgreSQL i ostatecznie zamieniają go na własną bazę danych. – John

+0

@John Powiedziałabym, że istnieje miliard i jeszcze jeden powód, dla którego należy postgres, i miliard więcej, aby nigdy nie dotykać mysql, ale tak - twój punkt jest nadal ważny :) – Ruslan

+0

@ John w tym czasie (2009) potrzebujemy prostszej bazy danych do radzenia sobie - i mysql był lepiej połączony z php – apelliciari

Odpowiedz

152

Następujące zapytanie podaje nazwy wszystkich sekwencji.

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

Zazwyczaj sekwencja nosi nazwę ${table}_id_seq. Proste dopasowywanie wzorca regex da ci nazwę tabeli.

Aby dostać ostatnia wartość sekwencji należy stosować następujące zapytanie:

SELECT last_value FROM test_id_seq; 
+5

Wskazówka "$ {table} _id_seq" była użyteczna –

41

Run: psql -E, a następnie \ds

+1

nie potrzebuję tylko listy sekwencji, potrzebuję tabeli, w której jest używana, następnej wartości itd. I muszę zrobić że w SQL – apelliciari

+0

Następnie, w każdej sekwencji ponownie \ d (nadal będąc w psql-E) –

+0

, to nie jest w SQL i nie pokazuje, przy której tabeli jest dołączona sekwencja – apelliciari

21

po trochę bólu, mam go.

najlepszym sposobem osiągnięcia tego celu jest lista wszystkich tabel

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

a następnie dla każdej tabeli, notować wszystkie kolumny z atrybutami

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

następnie dla każdej kolumny, testu, jeśli to ma sekwencję

select pg_get_serial_sequence('<table_name>', '<column_name>') 
, a następnie uzyskać informacje o tej sekwencji

2

Częściowo przetestowany, ale wygląda na kompletny.

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; 

kredytowych w przypadku gdy kredyt jest spowodowane ... to częściowo inżynierii odwrotnej z SQL zalogowanego od A \ D na znanej stole, który miał sekwencję. Jestem pewien, że też może być czystszy, ale hej, wydajność nie była problemem.

7

Zależność między automatycznie generowanych sekwencji (takie jak te utworzone Serial kolumn) i tabeli nadrzędnej jest modelowany przez atrybut właściciela sekwencja.

można zmodyfikować ten związek używając WŁASNOŚĆ klauzuli ALTER SEQUENCE commmand

np ZMIANA SEKWENCJI foo_id OWNED przez foo_schema.foo_table

je ustawić, aby wiązać się z tabeli foo_table

lub ALTER SEKWENCJI foo_id właSność BRAK

aby przerwać połączenie pomiędzy sekwencją oraz każda tablica

informacje o relacji jest przechowywany w pg_depend catalogue table.

relacja łączenia jest łączem między pg_depend.objid -> pg_class.oid WHERE relkind = 'S' - która łączy sekwencję z rekordem łączenia, a następnie pg_depend.refobjid -> pg_class.oid WHERE relkind = 'r' , która łączy rekord łączenia z relacją będącą właścicielem (tabela)

Ta kwerenda zwraca całą sekwencję -> zależności tabel w bazie danych. Klauzula where filtruje tylko relacje generowane automatycznie, co ogranicza je tylko do wyświetlania sekwencji utworzonych przez kolumny typu 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' ; 
0

Rodzaju hack, ale spróbuj tego:

wybierz 'wybierz ''' || relname || '' 'jako sekwencja, last_value od' || relname || "union" Z pg_catalog.pg_class c WHERE c.relkind IN ("S", "');

usunąć ostatni Unia i wykonać wynikiem

0

Poprawa poprzedniej odpowiedzi:

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

Proszę nie umieszczać kodu bez żadnych wyjaśnień. Ponadto, ponieważ stwierdziłeś, że twój kod jest "Poprawą poprzedniej odpowiedzi", powinieneś również powiedzieć nam, DLACZEGO to jest poprawa. Och, nie poddawaj się i witaj w SO! – Joel

+0

Czy powinienem napisać stronę bezsensownego tekstu zamiast dokładnego kodu (kilka linii)? –

+1

Nigdy tego nie mówiłem. Lubię prosty, precyzyjny kod. Ale kiedy stwierdzasz, że twój kod jest ulepszony, jedna lub dwie linijki wyjaśniające, dlaczego jest to poprawa (lepsza czytelność, poprawiona wydajność itp.), Nie zaszkodzi. Prawdopodobnie otrzymasz też ode mnie +1. – Joel

32

uwaga, że ​​począwszy od PostgreSQL 8.4 można uzyskać wszystkie informacji o sekwencji stosowanych w baza danych przez:

SELECT * FROM information_schema.sequences; 

Ponieważ używam wyższej wersji PostgreSQL (9.1) i szukałem tej samej odpowiedzi na wysokim i niskim poziomie, dodałem tę odpowiedź dla dobra przyszłych pokoleń i przyszłych poszukiwaczy.

+1

Miałem nadzieję, że ktoś będzie myśleć o potomności gdzieś tutaj w odpowiedziach ... +1 – SeldomNeedy

+1

Protip: sortuj odpowiedzi według "aktywnych". Potomność staje się coraz bardziej istotna, ponieważ pytania stają się coraz starsze .. – raveren

+1

Fajnie. I wygląda na to, że jeśli wybiorę "aktywną" metodę sortowania, strona po prostu zapamiętuje ustawienie od razu (tutaj szukałem miejsca, by ustawić to jako domyślne bez skutku). Hm, teraz, gdybyśmy tylko mieli "odpowiedź akceptowaną przez pytającego, nie przejmowałaby automatycznie wszystkiego innego" - opcja, * że * byłaby naprawdę wielkim zwycięstwem dla potomności. – SeldomNeedy

2

Wiem, że ten post jest dość stary, ale znalazłem rozwiązanie przez CMS, aby było bardzo przydatne, ponieważ szukałem zautomatyzowanego sposobu łączenia sekwencji z kolumną tabeli i chciałem się nią podzielić. Kluczem była tabela katalogowa pg_depend. Rozszerzyłem to, co zostało zrobione:

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

Ta wersja dodaje kolumnę do listy zwróconych pól. Mając zarówno nazwę tabeli, jak i nazwę kolumny, wywołanie pg_set_serial_sequence ułatwia zapewnienie, że wszystkie sekwencje w bazie danych są ustawione poprawnie. Na przykład:

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

Mam nadzieję, że to pomoże komuś w zresetowaniu sekwencji!

0

To stwierdzenie można znaleźć tabelę i kolumnę, który jest skojarzony z każdej sekwencji:

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' 

więcej zobacz tutaj link to answer

0

Dzięki za pomoc.

Oto funkcja pl/pgsql, która aktualizuje każdą sekwencję bazy danych. Informacje

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

sekwencja: wartość max

SELECT * FROM information_schema.sequences;

informacji sekwencja: ostatnia wartość

SELECT * FROM <sequence_name>

0

Oto jeszcze jeden, który ma nazwę schematu obok nazwy sekwencji

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