แสดงรายการลำดับทั้งหมดใน Postgres db 8.1 ด้วย SQL


147

ฉันแปลง db จาก postgres เป็น mysql

เนื่องจากฉันไม่สามารถหาเครื่องมือที่หลอกลวงได้ฉันจะเปลี่ยนลำดับ postgres ทั้งหมดเป็น autoincrement id ใน mysql ด้วยค่า autoincrement

ดังนั้นฉันจะแสดงรายการลำดับทั้งหมดในPostgres DB ( เวอร์ชัน8.1 ) ด้วยข้อมูลเกี่ยวกับตารางที่ใช้ค่าอื่น ๆ ถัดไปที่มีคิวรี่ SQL ได้อย่างไร

ระวังว่าฉันไม่สามารถใช้information_schema.sequencesมุมมองในรีลีส 8.4


1
ควรสังเกตว่าคุณกำลังทำ Conversion อย่างผิดวิธี ตั้งแต่ Oracle ซื้อ Sun พวกเขาช้าฆ่า MySQL ดังนั้นถ้าคุณดูถูกลูกค้าของคุณ (ซึ่งในกรณีที่คุณควรเลิก) คุณควรติดกับ PostgreSQL เนื่องจากไม่มี บริษัท (pro-monopoly ไม่ได้) เข้ามาพร้อมกันฮุบ PostgreSQL และ ในที่สุดแทนที่ด้วยฐานข้อมูลของตนเอง
John

@ John ผมบอกว่ามีเป็นพันล้านและเป็นหนึ่งในเหตุผลอื่น ๆ ที่จะติดกับ Postgres และพันล้านมากขึ้นเพื่อ MySQL ไม่เคยสัมผัส แต่ใช่ - จุดของคุณยังคงถูกต้องมาก :)
Ruslan

@John ในเวลา (2009) เราต้องการฐานข้อมูลที่ง่ายกว่าในการจัดการ - และ mysql เชื่อมโยงกับ PHP ได้ดีขึ้น
apelliciari

คำตอบ:


251

แบบสอบถามต่อไปนี้ให้ชื่อของลำดับทั้งหมด

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

${table}_id_seqโดยปกติจะเป็นลำดับที่มีชื่อเป็น การจับคู่รูปแบบ regex แบบง่ายจะให้ชื่อตาราง

ในการรับค่าสุดท้ายของลำดับให้ใช้เคียวรีต่อไปนี้:

SELECT last_value FROM test_id_seq;

5
${table}_id_seqคำใบ้มีประโยชน์
ปิแอร์เดอ LESPINAY

${table}_${column}_seqสำหรับลำดับที่สร้างขึ้นอัตโนมัติ
Evgeny Nozdrev

81

โปรดทราบว่าเริ่มต้นจาก PostgreSQL 8.4 คุณสามารถรับข้อมูลทั้งหมดเกี่ยวกับลำดับที่ใช้ในฐานข้อมูลผ่าน:

SELECT * FROM information_schema.sequences;

เนื่องจากฉันใช้รุ่นที่สูงกว่าของ PostgreSQL (9.1) และกำลังค้นหาคำตอบเดียวกันทั้งสูงและต่ำฉันจึงเพิ่มคำตอบนี้เพื่อประโยชน์ของลูกหลานและผู้ค้นหาในอนาคต


1
Protip: เรียงลำดับคำตอบด้วย "active" ลูกหลานได้รับมากขึ้นและมีความเกี่ยวข้องมากขึ้นเป็นคำถามจะกลายเป็นที่เก่ามากขึ้น ..
raveren

1
เย็น. และดูเหมือนว่าถ้าฉันเลือกวิธีการเรียงลำดับ "ใช้งานอยู่" เว็บไซต์จะจำการตั้งค่าได้ทันที (ที่นี่ฉันกำลังขุดไปรอบ ๆ เพื่อหาสถานที่ที่จะตั้งเป็นค่าเริ่มต้นโดยไม่มีประโยชน์) หืมตอนนี้ถ้าเพียงเราเท่านั้นที่มี "คำตอบที่ยอมรับโดยผู้ถามไม่ได้รวมทุกอย่างอื่นโดยอัตโนมัติ" - ตัวเลือกนั่นจะเป็นชัยชนะที่ยิ่งใหญ่อย่างแท้จริงสำหรับลูกหลาน
SeldomNeedy

หมายเหตุแน่ใจว่าตารางนี้เป็นที่รู้จักใน PG 8.4 ฉันอยากจะบอกว่า PG 8.2 หลังจากเอกสารอย่างเป็นทางการ: postgresql.org/docs/8.2/infoschema-sequences.html
กีโยม Husta

"ข้อมูลทั้งหมด" นั้นไม่รวมค่าปัจจุบัน
บาร์

62

เรียกใช้: psql -Eแล้ว\ds


1
ฉันไม่ได้ต้องการเพียงรายชื่อลำดับที่ฉันต้องการตารางในการที่จะใช้ค่าต่อไป ฯลฯ .. และฉันต้องทำแบบนั้นใน SQL
apelliciari

จากนั้นในทุกลำดับทำ \ d <name> (ยังคงอยู่ใน 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

ความสัมพันธ์ระหว่างลำดับที่สร้างขึ้นโดยอัตโนมัติ (เช่นที่สร้างขึ้นสำหรับคอลัมน์ SERIAL) และตารางแม่ถูกสร้างแบบจำลองโดยแอตทริบิวต์เจ้าของลำดับ

คุณสามารถแก้ไขความสัมพันธ์นี้โดยใช้ OWNED BY clause ของคำสั่งALTER SEQUENCE commmand

เช่น ALTER SEQUENCE foo_id เป็นเจ้าของโดย foo_schema.foo_table

เพื่อตั้งค่าให้เชื่อมโยงกับตาราง foo_table

หรือแก้ไขลำดับ foo_id เป็นเจ้าของโดย NONE

เพื่อหยุดการเชื่อมต่อระหว่างลำดับและตารางใด ๆ

ข้อมูลเกี่ยวกับความสัมพันธ์นี้จะถูกเก็บไว้ในตารางแคตตาล็อก pg_depend

ความสัมพันธ์ที่เข้าร่วมคือการเชื่อมโยงระหว่าง pg_depend.objid -> pg_class.oid WHERE relkind = 'S' - ซึ่งเชื่อมโยงลำดับไปยังบันทึกการเข้าร่วมแล้ว pg_depend.refobjid -> pg_class.oid WHERE relkind = 'r' ซึ่งเชื่อมโยง เข้าร่วมบันทึกการเป็นเจ้าของความสัมพันธ์ (ตาราง)

เคียวรีนี้ส่งคืนลำดับทั้งหมด -> การพึ่งพาตารางในฐานข้อมูล ส่วนคำสั่ง where กรองให้รวมเฉพาะความสัมพันธ์ที่สร้างขึ้นอัตโนมัติซึ่งจะ จำกัด เฉพาะการแสดงลำดับที่สร้างโดยคอลัมน์ที่พิมพ์ 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' ;

คำอธิบายที่เป็นประโยชน์ของการอ้างอิงระหว่างตารางและลำดับ แต่การค้นหาของคุณไม่พบลำดับทั้งหมดสำหรับฉัน ดูเหมือนว่ามีบางลำดับที่ไม่มีการอ้างอิงใด ๆ
Evgeny Nozdrev

ใช่แบบสอบถามนี้แสดงให้เห็นถึงลำดับที่กำหนดโดยนิยามคอลัมน์ฐานข้อมูลแบบอนุกรมเท่านั้น นี่คือคำอธิบายในคำตอบ
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$;

หวังว่านี่จะช่วยให้คนที่มีลำดับการรีเซ็ต!


ไม่กี่ปีที่ผ่านมาฉันสังเกตเห็นการปรับปรุงของคุณและป๊อปอัพโดยให้ upvote :-)
ซม.

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
โปรดอย่าเพิ่งใส่รหัสของคุณโดยไม่มีคำอธิบายใด ๆ นอกจากนี้เนื่องจากคุณระบุว่ารหัสของคุณคือ "การปรับปรุงคำตอบก่อนหน้า" คุณควรแจ้งให้เราทราบด้วยว่าทำไมจึงเป็นการปรับปรุง โอ้อย่ายอมแพ้และยินดีต้อนรับ SO!
Joel

ฉันควรเขียนหน้าของข้อความที่ไม่รู้สึกแทนรหัสที่แม่นยำ (สองบรรทัด) หรือไม่?
Alexander Ryabov

2
ไม่เคยพูดอย่างนั้น ฉันชอบรหัสที่เรียบง่ายและแม่นยำ แต่เมื่อระบุว่าโค้ดของคุณเป็นการปรับปรุงหนึ่งหรือสองบรรทัดอธิบายว่าทำไมมันถึงเป็นการปรับปรุง (ความสามารถในการอ่านที่ดีขึ้นประสิทธิภาพที่ดีขึ้นและอื่น ๆ ) จะไม่เจ็บ และคุณอาจได้รับ +1 จากฉันเช่นกัน
Joel

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' '' || relname || '' 'ตามลำดับ last_value จาก' || relname || 'union' จาก pg_catalog.pg_class c WHERE c.relkind IN ('S', '');

ลบ UNION ล่าสุดและดำเนินการผลลัพธ์


1

รับลำดับโดยแต่ละคอลัมน์ของแต่ละตารางผ่านการแยกส่วนของ DEFAULT clause วิธีนี้ให้ข้อมูลเกี่ยวกับลำดับของคอลัมน์ที่มีการเชื่อมโยงและไม่ได้ใช้การพึ่งพาซึ่งอาจไม่มีอยู่สำหรับบางลำดับ 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

ฟังก์ชันนี้แสดง last_value ของแต่ละลำดับ

มันส่งออกตาราง 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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.