SQL을 사용하여 Postgres db 8.1의 모든 시퀀스 나열


147

DB를 postgres에서 mysql로 ​​변환하고 있습니다.

트릭 자체를 수행하는 도구를 찾을 수 없으므로 모든 postgres 시퀀스를 자동 증가 값을 사용하여 mysql의 자동 증가 ID로 변환합니다.

그렇다면 Postgres DB ( 8.1 버전)의 모든 시퀀스를 사용하는 테이블에 대한 정보, 다음 값 등을 SQL 쿼리와 함께 어떻게 나열 할 수 있습니까?

information_schema.sequences8.4 릴리스 에서는 보기를 사용할 수 없습니다 .


1
변환을 잘못하고 있습니다. 오라클이 Sun을 인수했기 때문에 천천히 MySQL을 죽이고 있습니다. 따라서 클라이언트를 멸시하지 않으면 (단순히 종료해야 함) PostgreSQL을 고수해야합니다 (프로 독점은 아닙니다). 결국 자체 데이터베이스로 대체하십시오.
John

@ 존 나는 postgres를 고수 할 수있는 10 억 가지의 다른 이유가 있다고 말하고, mysql을 절대 만지지 않는 10 억 개가 더 있지만, 요점-여전히 유효합니다 :)
Ruslan

시간 (2009 년) 우리가 처리 할 수있는 간단한 데이터베이스가 필요에 @ 존 - 그리고 MySQL은 더 나은 PHP를 결합했다
apelliciari

답변:


251

다음 쿼리는 모든 시퀀스의 이름을 제공합니다.

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

일반적으로 시퀀스의 이름은 ${table}_id_seq입니다. 간단한 정규식 패턴 일치는 테이블 이름을 제공합니다.

시퀀스의 마지막 값을 얻으려면 다음 쿼리를 사용하십시오.

SELECT last_value FROM test_id_seq;

5
${table}_id_seq힌트 유용
피에르 드 LESPINAY

${table}_${column}_seq자동 생성 시퀀스
Evgeny Nozdrev

80

PostgreSQL 8.4부터는 다음을 통해 데이터베이스에서 사용되는 시퀀스에 대한 모든 정보를 얻을 수 있습니다 .

SELECT * FROM information_schema.sequences;

나는 더 높은 버전의 PostgreSQL (9.1)을 사용하고 있으며 동일한 답변을 높고 낮게 검색했기 때문에 후손을 위해 그리고 미래의 검색자를 위해이 답변을 추가했습니다.


1
팁 : 답변을 "활성"으로 정렬하십시오. 질문은 점점 더 오래된되고있다으로 후대 .. 더 많은 관련 얻는다
raveren

1
멋있는. 그리고 "활성"정렬 방법을 선택하면 사이트에서 설정을 바로 기억합니다 (여기서는 기본 설정으로 사용할 수없는 곳을 찾기 위해 환경 설정을 파고있었습니다). 흠, 이제 우리가 "구할 수있는 대답이 다른 모든 것을 자동으로 능가하지 않는다"는 선택권 만 있다면, 그것은 후손 에게는 정말로 승리 일 것입니다.
SeldomNeedy

이 표가 PG 8.4에 도입되었는지 확인하십시오. 공식 문서 다음에 PG 8.2라고 말하고 싶습니다 : postgresql.org/docs/8.2/infoschema-sequences.html
Guillaume Husta

"모든 정보"에는 현재 값이 포함되지 않습니다.
bart

62

: 실행 psql -E다음과\ds


1
시퀀스 목록 만 필요하지 않습니다. 사용 된 테이블, 다음 값 등이 필요합니다. 그리고 SQL에서이를 수행해야합니다.
apelliciari

그런 다음 모든 시퀀스에서 \ d <name> (여전히 psql -E에 있음)

다시 말하지만 이것은 SQL에 없으며 시퀀스가 ​​첨부 된 테이블을 보여주지 않습니다
apelliciari

@ avastreg : 내가 말한대로 실행 했습니까? 왜 안돼?

10
@avastreg : 그냥 해 ONCE . 그리고 그것은 당신에게 쿼리를 보여줄 것입니다!

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 컬럼에 대해 작성된 시퀀스)와 상위 테이블 간의 관계는 시퀀스 소유자 속성으로 모델링됩니다.

ALTER SEQUENCE 명령 의 OWNED BY 절을 사용하여이 관계를 수정할 수 있습니다.

예 : ALTER SEQUENCE foo_id foo_schema.foo_table이 소유 함

foo_table 테이블에 연결되도록 설정

또는 NONE이 소유 한 ALTER SEQUENCE foo_id

시퀀스와 테이블 간의 연결을 끊기

이 관계에 대한 정보는 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 :-)
cms

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;

크레디트가 필요한 크레디트 ... 시퀀스가있는 알려진 테이블의 \ d에서 로그 된 SQL에서 부분적으로 리버스 엔지니어링되었습니다. 나는 그것이 더 깨끗할 수 있다고 확신하지만, 성능은 문제가되지 않았습니다.


1

해킹 종류이지만 다음을 시도하십시오.

'select' ''선택 || relname || 순서대로 '' ', from ||의 last_value relname || pg_catalog.pg_class c에서 'union'c.relkind IN ( 'S', '');

마지막 UNION을 제거하고 결과를 실행하십시오.


1

DEFAULT 절의 구문 분석을 통해 각 테이블의 각 열별로 시퀀스를 가져옵니다. 이 방법은 어떤 열 시퀀스가 ​​연결되는지에 대한 정보를 제공 하며 일부 시퀀스 에는 없을 수있는 종속성 을 사용하지 않습니다 . 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;

하나의 시퀀스를 여러 테이블에서 사용할 수 있으므로 여기에서 여러 행으로 나열 할 수 있습니다.


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

다음은 시퀀스 이름 옆에 스키마 이름이있는 다른 것입니다.

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

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.