모든 PK 및 FK 검색


20

각 테이블에서 모든 기본 키와 외래 키를 추출 해야하는 큰 데이터베이스가 있습니다.

pgAdmin III이 있습니다.

이 작업을 자동으로 수행하고 각 테이블을 수동으로 거치지 않는 방법이 있습니까?

답변:


31

pg_get_constraintdef(constraint_oid)다음과 같은 쿼리 에서 함수 를 사용할 수 있습니다 .

SELECT conrelid::regclass AS table_from
     , conname
     , pg_get_constraintdef(oid)
FROM   pg_constraint
WHERE  contype IN ('f', 'p ')
AND    connamespace = 'public'::regnamespace  -- your schema here
ORDER  BY conrelid::regclass::text, contype DESC;

결과:

 table_from | conname    | pg_get_constraintdef
------------+------------+----------------------
 tbl        | tbl_pkey   | PRIMARY KEY (tbl_id)
 tbl        | tbl_col_fk | FOREIGN KEY (col) REFERENCES tbl2(col) ON UPDATE CASCADE
...

주어진 스키마에있는 모든 테이블의 모든 기본 키와 외래 키를 테이블 이름 PK 순서로 반환합니다.

에 대한 매뉴얼 pg_constraint.

대한 수동 객체 식별자 유형 ( regclass, regnamespace, ...).


1
조건이 고유 제한 조건을 리턴하는 위치가 수정되었습니다.WHERE contype IN ('f', 'p', 'u')
Daniel Waltrip

9

Erwin 솔루션을 기반으로 :

SELECT conrelid::regclass AS "FK_Table"
      ,CASE WHEN pg_get_constraintdef(c.oid) LIKE 'FOREIGN KEY %' THEN substring(pg_get_constraintdef(c.oid), 14, position(')' in pg_get_constraintdef(c.oid))-14) END AS "FK_Column"
      ,CASE WHEN pg_get_constraintdef(c.oid) LIKE 'FOREIGN KEY %' THEN substring(pg_get_constraintdef(c.oid), position(' REFERENCES ' in pg_get_constraintdef(c.oid))+12, position('(' in substring(pg_get_constraintdef(c.oid), 14))-position(' REFERENCES ' in pg_get_constraintdef(c.oid))+1) END AS "PK_Table"
      ,CASE WHEN pg_get_constraintdef(c.oid) LIKE 'FOREIGN KEY %' THEN substring(pg_get_constraintdef(c.oid), position('(' in substring(pg_get_constraintdef(c.oid), 14))+14, position(')' in substring(pg_get_constraintdef(c.oid), position('(' in substring(pg_get_constraintdef(c.oid), 14))+14))-1) END AS "PK_Column"
FROM   pg_constraint c
JOIN   pg_namespace n ON n.oid = c.connamespace
WHERE  contype IN ('f', 'p ')
AND pg_get_constraintdef(c.oid) LIKE 'FOREIGN KEY %'
ORDER  BY pg_get_constraintdef(c.oid), conrelid::regclass::text, contype DESC;

다음과 같은 형식의 테이블을 반환합니다.

| FK_Table | FK_Column | PK_Table | PK_Column |

이것이 바로 HeidiSQL이 외래 키 정의를 검색하는 데 필요한 것입니다. 같은 더 우아 할 수있는 방법은 적은 비용으로, 거기에 LIKE, SUBSTRINGPOSITION전화? 나는 거의 거기에 있지만 열은 query 와 함께 두 번 나열됩니다 .
Anse

5

구문 분석 할 필요가 없으며 테이블의 pg_get_constraintdef()열을 사용 pg_constraint하여 다른 세부 정보 ( docs ) 를 얻으십시오 .

여기 constraint_type있을 수 있습니다 :

  • P - 기본 키 ,
  • F - 외래 키 ,
  • u- 독특 하고
  • C - 점검 제한 조건 ,
  • X - 배제 ,
  • ...

Erwin의 답변을 바탕으로 :

SELECT c.conname                                 AS constraint_name,
   c.contype                                     AS constraint_type,
   sch.nspname                                   AS "self_schema",
   tbl.relname                                   AS "self_table",
   ARRAY_AGG(col.attname ORDER BY u.attposition) AS "self_columns",
   f_sch.nspname                                 AS "foreign_schema",
   f_tbl.relname                                 AS "foreign_table",
   ARRAY_AGG(f_col.attname ORDER BY f_u.attposition) AS "foreign_columns",
   pg_get_constraintdef(c.oid)                   AS definition
FROM pg_constraint c
       LEFT JOIN LATERAL UNNEST(c.conkey) WITH ORDINALITY AS u(attnum, attposition) ON TRUE
       LEFT JOIN LATERAL UNNEST(c.confkey) WITH ORDINALITY AS f_u(attnum, attposition) ON f_u.attposition = u.attposition
       JOIN pg_class tbl ON tbl.oid = c.conrelid
       JOIN pg_namespace sch ON sch.oid = tbl.relnamespace
       LEFT JOIN pg_attribute col ON (col.attrelid = tbl.oid AND col.attnum = u.attnum)
       LEFT JOIN pg_class f_tbl ON f_tbl.oid = c.confrelid
       LEFT JOIN pg_namespace f_sch ON f_sch.oid = f_tbl.relnamespace
       LEFT JOIN pg_attribute f_col ON (f_col.attrelid = f_tbl.oid AND f_col.attnum = f_u.attnum)
GROUP BY constraint_name, constraint_type, "self_schema", "self_table", definition, "foreign_schema", "foreign_table"
ORDER BY "self_schema", "self_table";

결과는 schema및 로 정렬됩니다 table.

기술 주 : 이 질문 에 대한을 with ordinality.


1
결과를 구문 분석하지 않고도 참조 된 열과 테이블 및 스키마를 검색하는 방법이 궁금합니다 pg_get_constraintdef().
Anse

1
@Anse가 답변을 업데이트했습니다. 아이디어 주셔서 감사합니다.
Evgeny Nozdrev

1

최근에는 정보 스키마를 기반으로 CRUD 유틸리티를 구축하는 데이터 액세스 계층 (Data Access Layer)에이를 구현해야했으며 결국이 방식으로 진행되었습니다.

SELECT

    current_schema() AS "schema",
    current_catalog AS "database",
    "pg_constraint".conrelid::regclass::text AS "primary_table_name",
    "pg_constraint".confrelid::regclass::text AS "foreign_table_name",

    (
        string_to_array(
            (
                string_to_array(
                    pg_get_constraintdef("pg_constraint".oid),
                    '('
                )
            )[2],
            ')'
        )
    )[1] AS "foreign_column_name",

    "pg_constraint".conindid::regclass::text AS "constraint_name",

    TRIM((
        string_to_array(
            pg_get_constraintdef("pg_constraint".oid),
            '('
        )
    )[1]) AS "constraint_type",

    pg_get_constraintdef("pg_constraint".oid) AS "constraint_definition"

FROM pg_constraint AS "pg_constraint"

JOIN pg_namespace AS "pg_namespace" ON "pg_namespace".oid = "pg_constraint".connamespace

WHERE

    "pg_constraint".contype IN ( 'f', 'p' )
    AND
    "pg_namespace".nspname = current_schema()
    AND
    "pg_constraint".conrelid::regclass::text IN ('whatever_table_name')
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.