Liệt kê tất cả các chuỗi trong Postgres db 8.1 bằng SQL


147

Tôi đang chuyển đổi một db từ postgres sang mysql.

Vì tôi không thể tìm thấy một công cụ tự lừa mình, tôi sẽ chuyển đổi tất cả các chuỗi postgres thành id tự động trong mysql với giá trị tự động tăng.

Vì vậy, làm thế nào tôi có thể liệt kê tất cả các chuỗi trong Postgres DB ( phiên bản 8.1 ) với thông tin về bảng được sử dụng, giá trị tiếp theo, v.v với truy vấn SQL?

Xin lưu ý rằng tôi không thể sử dụng information_schema.sequenceschế độ xem trong bản phát hành 8.4.


1
Cần lưu ý rằng bạn đang thực hiện chuyển đổi sai cách. Vì Oracle đã mua Sun, họ đã dần giết chết MySQL vì vậy trừ khi bạn coi thường khách hàng của mình (trong trường hợp đó bạn nên bỏ đơn giản), bạn nên gắn bó với PostgreQuery vì không có công ty nào (không độc quyền) có thể xuất hiện, gặm nhấm PostgreQuery và cuối cùng thay thế nó bằng cơ sở dữ liệu riêng của họ.
Giăng

@ John Tôi muốn nói rằng có một tỷ và một lý do khác để gắn bó với postgres, và một tỷ nữa để không bao giờ chạm vào mysql, nhưng vâng - quan điểm của bạn vẫn rất hợp lệ :)
Ruslan

@ John vào thời điểm đó (2009) chúng ta cần một cơ sở dữ liệu đơn giản hơn để xử lý - và mysql được kết hợp tốt hơn với php
apelliciari

Câu trả lời:


250

Các truy vấn sau đây cho tên của tất cả các chuỗi.

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

Thông thường một chuỗi được đặt tên là ${table}_id_seq. Kết hợp mẫu regex đơn giản sẽ cung cấp cho bạn tên bảng.

Để nhận giá trị cuối cùng của chuỗi, sử dụng truy vấn sau:

SELECT last_value FROM test_id_seq;

5
Các ${table}_id_seqgợi ý hữu ích
Pierre de LESPINAY

${table}_${column}_seqcho các chuỗi được tạo tự động
Evgeny Nozdrev 18/07/18

80

Lưu ý, bắt đầu từ PostgreSQL 8.4, bạn có thể nhận được tất cả thông tin về các chuỗi được sử dụng trong cơ sở dữ liệu thông qua:

SELECT * FROM information_schema.sequences;

Vì tôi đang sử dụng phiên bản cao hơn của PostgreSQL (9.1) và đang tìm kiếm cùng một câu trả lời cao và thấp, tôi đã thêm câu trả lời này cho mục đích của hậu thế và cho những người tìm kiếm trong tương lai.


1
Protip: sắp xếp các câu trả lời theo "hoạt động".
Hậu thế

1
Mát mẻ. Và có vẻ như nếu tôi chọn phương pháp sắp xếp "hoạt động", trang web chỉ cần nhớ cài đặt ngay lập tức (ở đây tôi đang tìm hiểu các tùy chọn để tìm một nơi để đặt mặc định thành không có hiệu lực). Hừm, bây giờ nếu chúng ta chỉ có một "câu trả lời được người hỏi chấp nhận thì không tự động thổi phồng mọi thứ khác", đó sẽ là một chiến thắng thực sự tuyệt vời cho hậu thế.
SeldomNeedy

Lưu ý rằng bảng này đã được giới thiệu trong PG 8.4, tôi muốn nói là PG 8.2 sau tài liệu chính thức: postgresql.org/docs/8.2/infoschema-
resultences.html

Rằng "tất cả thông tin" không bao gồm giá trị hiện tại.
bart

62

Chạy: psql -Evà sau đó\ds


1
Tôi không chỉ cần danh sách các chuỗi, tôi cần bảng được sử dụng, giá trị tiếp theo, v.v. Và tôi phải làm điều đó trong SQL
apelliciari

Sau đó, trên mỗi chuỗi làm \ d <name> (vẫn còn trong psql -E)

một lần nữa, đây không phải là SQL và không hiển thị trình tự nào được đính kèm
apelliciari

@avastreg: bạn đã chạy nó theo cách tôi đã nói với bạn chưa? và tại sao không?

10
@avastreg: JUST DO IT MỘT LẦN . Và nó sẽ cho bạn thấy các truy vấn!

26

Sau một chút đau đớn, tôi đã nhận được nó.

cách tốt nhất để đạt được điều này là liệt kê tất cả các bảng

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

và sau đó, cho mỗi bảng, liệt kê tất cả các cột có thuộc tính

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

sau đó, cho mỗi cột, kiểm tra nếu nó có một chuỗi

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

và sau đó, có được thông tin về trình tự này

select * from <sequence_name>

13

thông tin trình tự: giá trị tối đa

SELECT * FROM information_schema.sequences;

thông tin trình tự: giá trị cuối cùng

SELECT * FROM <sequence_name>


11

Mối quan hệ giữa các chuỗi được tạo tự động (chẳng hạn như các chuỗi được tạo cho các cột SERIAL) và bảng cha được mô hình hóa bởi thuộc tính chủ sở hữu chuỗi.

Bạn có thể sửa đổi mối quan hệ này bằng cách sử dụng mệnh đề SỞ HỮU BỞI của ủy ban ALTER SEQUENCE

ví dụ: ALTER SEQUENCE foo_id SỞ HỮU bởi foo_schema.foo_table

để đặt nó được liên kết với bảng foo_table

hoặc ALTER SEQUENCE foo_id SỞ HỮU

phá vỡ kết nối giữa chuỗi và bất kỳ bảng nào

Thông tin về mối quan hệ này được lưu trữ trong bảng danh mục pg_depend .

mối quan hệ tham gia là liên kết giữa pg_depend.objid -> pg_group.oid WHERE relkind = 'S' - liên kết chuỗi với bản ghi tham gia và sau đó pg_depend.refobjid -> pg_ class.oid WHERE relkind = 'r', liên kết tham gia hồ sơ để quan hệ sở hữu (bảng)

Truy vấn này trả về tất cả các chuỗi -> phụ thuộc bảng trong cơ sở dữ liệu. Mệnh đề where lọc nó chỉ bao gồm các mối quan hệ được tạo tự động, điều này hạn chế nó chỉ hiển thị các chuỗi được tạo bởi các cột được gõ 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' ;

Giải thích hữu ích về sự phụ thuộc giữa các bảng và trình tự. Nhưng truy vấn của bạn tìm thấy không phải tất cả các trình tự cho tôi. Dường như một số trình tự tồn tại mà không có bất kỳ sự phụ thuộc.
Evgeny Nozdrev

có, truy vấn này rõ ràng chỉ thể hiện các chuỗi được xác định bởi các định nghĩa cột nối tiếp cơ sở dữ liệu. Điều này được giải thích trong câu trả lời.
cms

5

Tôi biết bài đăng này khá cũ, nhưng tôi thấy giải pháp của CMS rất hữu ích vì tôi đang tìm kiếm một cách tự động để liên kết một chuỗi với cột VÀ cột và muốn chia sẻ. Việc sử dụng bảng danh mục pg_depend là chìa khóa. Tôi đã mở rộng những gì đã được thực hiện để:

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

Phiên bản này thêm cột vào danh sách các trường được trả về. Với cả tên bảng và tên cột trong tay, một lệnh gọi pg_set_serial_ resultence giúp dễ dàng đảm bảo rằng tất cả các chuỗi trong cơ sở dữ liệu được đặt chính xác. Ví dụ:

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

Hy vọng điều này sẽ giúp ai đó với việc thiết lập lại trình tự!


Một vài năm sau, tôi nhận thấy bản cập nhật của bạn và bật lên để đưa ra một upvote :-)
cms

3

Câu lệnh này liệt kê bảng và cột được liên kết với mỗi chuỗi:

Mã số:

    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'

xem thêm ở đây liên kết để trả lời


2

Cải thiện câu trả lời trước:

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
Xin vui lòng không đặt mã của bạn mà không có bất kỳ lời giải thích. Ngoài ra, vì bạn đã tuyên bố rằng mã của bạn là "Cải thiện câu trả lời trước", bạn cũng nên cho chúng tôi biết TẠI SAO đó là một cải tiến. Oh, đừng bỏ cuộc, và chào mừng bạn đến với SO!
Joel

Tôi có nên viết một trang văn bản vô nghĩa thay vì mã chính xác (vài dòng) không?
Alexander Ryabov

2
Không bao giờ nói rằng. Tôi thích mã đơn giản, chính xác. Nhưng khi nói rằng mã của bạn là một cải tiến, một hoặc hai dòng giải thích TẠI SAO đó là một cải tiến (khả năng đọc tốt hơn, hiệu suất được cải thiện, v.v.) sẽ không bị tổn thương. Và có lẽ bạn cũng sẽ nhận được +1 từ tôi.
Joel

1

Thử nghiệm một phần nhưng có vẻ hầu như hoàn thành.

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;

Tín dụng khi tín dụng đáo hạn ... nó được thiết kế ngược một phần từ SQL được ghi từ \ d trên một bảng đã biết có trình tự. Tôi chắc rằng nó cũng có thể sạch hơn, nhưng này, hiệu suất không phải là vấn đề đáng lo ngại.


1

Một loại hack, nhưng hãy thử điều này:

chọn 'chọn' '' | | tên hiệu | | '' 'là chuỗi, last_value từ' || tên hiệu | | 'union' TỪ pg_catalog.pg_group c WHERE c.relkind IN ('S', '');

Xóa UNION cuối cùng và thực hiện kết quả


1

Nhận các chuỗi theo từng cột của mỗi bảng thông qua phân tích mệnh đề DEFAULT. Phương pháp này cung cấp thông tin về các chuỗi cột được liên kết và không sử dụng các phụ thuộc có thể không tồn tại cho một số chuỗi. Ngay cả pg_get_serial_sequence(sch.nspname||'.'||tbl.relname, col.attname)chức năng tìm thấy không phải tất cả các trình tự cho tôi!

Giải pháp:

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;

Lưu ý rằng 1 chuỗi có thể được sử dụng trong nhiều bảng, vì vậy nó có thể được liệt kê trong nhiều hàng ở đây.


0

Cảm ơn bạn đã giúp đỡ.

Đây là hàm pl / pssql cập nhật từng chuỗi cơ sở dữ liệu.

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

Đây là một cái khác có tên lược đồ bên cạnh tên chuỗi

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

0

Hàm này hiển thị last_value của mỗi chuỗi.

Nó xuất ra một bảng 2 cột cho biết tên chuỗi cộng với giá trị được tạo cuối cùng của nó.

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()Hàm giả sử được khai báo trong bài đăng này https://stackoverflow.com/a/46721603/653539 , các chuỗi cùng với các giá trị cuối cùng của chúng có thể được tìm nạp bằng một truy vấn duy nhất:

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

Dưới đây là một ví dụ về cách sử dụng psqlđể có được danh sách tất cả các chuỗi với 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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.