외래 키 및 이들이 참조하는 테이블 목록


143

테이블의 외래 키 목록과 참조하는 테이블과 열을 반환하는 쿼리를 찾으려고합니다. 나는 반쯤 거기에

SELECT a.table_name, 
       a.column_name, 
       a.constraint_name, 
       c.owner
FROM ALL_CONS_COLUMNS A, ALL_CONSTRAINTS C  
where A.CONSTRAINT_NAME = C.CONSTRAINT_NAME 
  and a.table_name=:TableName 
  and C.CONSTRAINT_TYPE = 'R'

그러나 여전히이 키가 참조하는 테이블과 기본 키를 알아야합니다. 어떻게 알 수 있습니까?


@MenelaosVergis 대답은 쉽게 나를 위해 잘 한 - stackoverflow.com/a/15364469/1579667
Benj

답변:


229

참조 된 기본 키 컬럼에서 설명 r_owner하고 r_constraint_name테이블의 ALL_CONSTRAINTS. 원하는 정보를 제공합니다.

SELECT a.table_name, a.column_name, a.constraint_name, c.owner, 
       -- referenced pk
       c.r_owner, c_pk.table_name r_table_name, c_pk.constraint_name r_pk
  FROM all_cons_columns a
  JOIN all_constraints c ON a.owner = c.owner
                        AND a.constraint_name = c.constraint_name
  JOIN all_constraints c_pk ON c.r_owner = c_pk.owner
                           AND c.r_constraint_name = c_pk.constraint_name
 WHERE c.constraint_type = 'R'
   AND a.table_name = :TableName

1
참고로, 위의 코드는 복합 외래 키를 고려하지 않습니다. 복합 키를 설명하는 방법에 대해서는 아래 @Dougman의 답변을 참조하십시오.
xkrz

2
여러 열에 정의 된 외래 키와 같이 @ xkrz 복합 외래 키? 위의 쿼리로 어떻게 고려되지 않을지 모르겠습니다!
Vincent Malgrat

1
@ VincentMalgrat, 사과, 내 실수. 귀하의 코드를 사용하여 제약 조건 이름 대신 참조 "TableName + ColumnName"을 나열하려고했지만 코드가하는 것이 아닙니다.
xkrz

1
c.owner가 첫 번째 열이 아니라고 귀찮게합니다. 그 우수성 이외 :)
roshan

1
@roshan 이제 언급했듯이, 열 순서는 약간 이상하다고 느낍니다.
Vincent Malgrat

33

이 시도:

select * from all_constraints where r_constraint_name in (select constraint_name 
from all_constraints where table_name='YOUR_TABLE_NAME');

3
OP가 실제로 무엇을하고 싶었는지는 완전히 명확하지는 않지만 대답은 완벽하게 작동하며 더 간단합니다. "Oracle에서 지정한 특정 테이블을 참조하는 외래 키를 얻는 방법은 무엇입니까? ". constraint_name을 사용하여 분석을 수행 할 수 있습니다. 팁 : 결과를 명확히하려면 "owner = 'MY_SCHEMA_HERE'"를 추가하십시오. 아주 좋아요
Diego1974

21

우리가 사용하는 다목적 스크립트는 매우 유용합니다.

직접 실행할 수 있도록 저장하십시오 (@ fkeys.sql). 소유자와 부모 또는 자식 테이블로 검색하고 외래 키 관계를 표시 할 수 있습니다. 현재 스크립트는 C : \ SQLRPTS로 명시 적으로 스풀링하므로 해당 행을 사용하려는 것으로 변경 폴더를 작성해야합니다.

REM ########################################################################
REM ##
REM ##   fkeys.sql
REM ##
REM ##   Displays the foreign key relationships
REM ##
REM #######################################################################

CLEAR BREAK
CLEAR COL
SET LINES 200
SET PAGES 54
SET NEWPAGE 0
SET WRAP OFF
SET VERIFY OFF
SET FEEDBACK OFF

break on table_name skip 2 on constraint_name on r_table_name skip 1

column CHILDCOL format a60 head 'CHILD COLUMN'
column PARENTCOL format a60 head 'PARENT COLUMN'
column constraint_name format a30 head 'FK CONSTRAINT NAME'
column delete_rule format a15
column bt noprint
column bo noprint

TTITLE LEFT _DATE CENTER 'FOREIGN KEY RELATIONSHIPS ON &new_prompt' RIGHT 'PAGE:'FORMAT 999 SQL.PNO SKIP 2

SPOOL C:\SQLRPTS\FKeys_&new_prompt
ACCEPT OWNER_NAME PROMPT 'Enter Table Owner (or blank for all): '
ACCEPT PARENT_TABLE_NAME PROMPT 'Enter Parent Table or leave blank for all: '
ACCEPT CHILD_TABLE_NAME PROMPT 'Enter Child Table or leave blank for all: '

  select b.owner || '.' || b.table_name || '.' || b.column_name CHILDCOL,
         b.position,
         c.owner || '.' || c.table_name || '.' || c.column_name PARENTCOL,
         a.constraint_name,
         a.delete_rule,
         b.table_name bt,
         b.owner bo
    from all_cons_columns b,
         all_cons_columns c,
         all_constraints a
   where b.constraint_name = a.constraint_name
     and a.owner           = b.owner
     and b.position        = c.position
     and c.constraint_name = a.r_constraint_name
     and c.owner           = a.r_owner
     and a.constraint_type = 'R'
     and c.owner      like case when upper('&OWNER_NAME') is null then '%'
                                else upper('&OWNER_NAME') end
     and c.table_name like case when upper('&PARENT_TABLE_NAME') is null then '%'
                                else upper('&PARENT_TABLE_NAME') end
     and b.table_name like case when upper('&CHILD_TABLE_NAME') is null then '%'
                                else upper('&CHILD_TABLE_NAME') end
order by 7,6,4,2
/
SPOOL OFF
TTITLE OFF
SET FEEDBACK ON
SET VERIFY ON
CLEAR BREAK
CLEAR COL
SET PAGES 24
SET LINES 100
SET NEWPAGE 1
UNDEF OWNER

12

주어진 테이블과 열에 대한 외래 키의 계층 구조를 이동하고 자식과 손자, 모든 자손 테이블의 열을 반환합니다. 하위 쿼리를 사용하여 r_table_name 및 r_column_name을 user_constraints에 추가 한 다음이를 사용하여 행을 연결합니다.

select distinct table_name, constraint_name, column_name, r_table_name, position, constraint_type 
from (
    SELECT uc.table_name, 
    uc.constraint_name, 
    cols.column_name, 
    (select table_name from user_constraints where constraint_name = uc.r_constraint_name) 
        r_table_name,
    (select column_name from user_cons_columns where constraint_name = uc.r_constraint_name and position = cols.position) 
        r_column_name,
    cols.position,
    uc.constraint_type
    FROM user_constraints uc
    inner join user_cons_columns cols on uc.constraint_name = cols.constraint_name 
    where constraint_type != 'C'
) 
start with table_name = 'MY_TABLE_NAME' and column_name = 'MY_COLUMN_NAME'  
connect by nocycle 
prior table_name = r_table_name 
and prior column_name = r_column_name;

8

다른 해결책이 있습니다. sys의 기본보기 사용은 너무 느립니다 (제 상황에서는 약 10 초). 이보다 훨씬 빠릅니다 (약 0.5 초).

SELECT
    CONST.NAME AS CONSTRAINT_NAME,
    RCONST.NAME AS REF_CONSTRAINT_NAME,

    OBJ.NAME AS TABLE_NAME,
    COALESCE(ACOL.NAME, COL.NAME) AS COLUMN_NAME,
    CCOL.POS# AS POSITION,

    ROBJ.NAME AS REF_TABLE_NAME,
    COALESCE(RACOL.NAME, RCOL.NAME) AS REF_COLUMN_NAME,
    RCCOL.POS# AS REF_POSITION
FROM SYS.CON$ CONST
INNER JOIN SYS.CDEF$ CDEF ON CDEF.CON# = CONST.CON#
INNER JOIN SYS.CCOL$ CCOL ON CCOL.CON# = CONST.CON#
INNER JOIN SYS.COL$ COL  ON (CCOL.OBJ# = COL.OBJ#) AND (CCOL.INTCOL# = COL.INTCOL#)
INNER JOIN SYS.OBJ$ OBJ ON CCOL.OBJ# = OBJ.OBJ#
LEFT JOIN SYS.ATTRCOL$ ACOL ON (CCOL.OBJ# = ACOL.OBJ#) AND (CCOL.INTCOL# = ACOL.INTCOL#)

INNER JOIN SYS.CON$ RCONST ON RCONST.CON# = CDEF.RCON#
INNER JOIN SYS.CCOL$ RCCOL ON RCCOL.CON# = RCONST.CON#
INNER JOIN SYS.COL$ RCOL  ON (RCCOL.OBJ# = RCOL.OBJ#) AND (RCCOL.INTCOL# = RCOL.INTCOL#)
INNER JOIN SYS.OBJ$ ROBJ ON RCCOL.OBJ# = ROBJ.OBJ#
LEFT JOIN SYS.ATTRCOL$ RACOL  ON (RCCOL.OBJ# = RACOL.OBJ#) AND (RCCOL.INTCOL# = RACOL.INTCOL#)

WHERE CONST.OWNER# = userenv('SCHEMAID')
  AND RCONST.OWNER# = userenv('SCHEMAID')
  AND CDEF.TYPE# = 4  /* 'R' Referential/Foreign Key */;

이것은 Oracle 10g에서 작동하지 않습니다. "_CURRENT_EDITION_OBJ"인식되지 않습니다.
StilesCrisis

2
안녕, 교체 SYS."_CURRENT_EDITION_OBJ"와 함께 SYS.OBJ$. 10g와 11g 모두에서 실행됩니다. 그리고 충분한 권한이 있는지 확인하십시오. 또한로 답변을 변경했습니다 SYS.OBJ$.
Ganbat Bayarbaatar

이 문장에 스키마 (OWNER)를 포함시키는 방법 (문자열 fe SYSTEM)?
Adam Mrozek

5

사용자의 외래 키가 모두 필요하면 다음 스크립트를 사용하십시오.

SELECT a.constraint_name, a.table_name, a.column_name,  c.owner, 
       c_pk.table_name r_table_name,  b.column_name r_column_name
  FROM user_cons_columns a
  JOIN user_constraints c ON a.owner = c.owner
       AND a.constraint_name = c.constraint_name
  JOIN user_constraints c_pk ON c.r_owner = c_pk.owner
       AND c.r_constraint_name = c_pk.constraint_name
  JOIN user_cons_columns b ON C_PK.owner = b.owner
       AND  C_PK.CONSTRAINT_NAME = b.constraint_name AND b.POSITION = a.POSITION     
 WHERE c.constraint_type = 'R'

Vincent Malgrat 코드 기반


사용자 제약 조건을 반환하지 않고 TABLE_NAME 및 R_TABLE_NAME에서 WRM $ _SNAPSHOT 및 WRM $ _DATABASE_INSTANCE 만 반환합니다.
instanceOfObject

5

답변이 늦었지만 어쨌든 대답하겠습니다. 위의 답변 중 일부는 매우 복잡하므로 여기에 훨씬 간단한 조치가 있습니다.

SELECT a.table_name child_table, a.column_name child_column, a.constraint_name, 
      b.table_name parent_table, b.column_name parent_column
  FROM all_cons_columns a
  JOIN all_constraints c ON a.owner = c.owner AND a.constraint_name = c.constraint_name
 join all_cons_columns b on c.owner = b.owner and c.r_constraint_name = b.constraint_name
 WHERE c.constraint_type = 'R'
   AND a.table_name = 'your table name'

1
이것은 나를 위해 여러 개의 중복 행을 반환했습니다. DISTINCT를 추가하고 정리했습니다.
Ray K.

1

UAT 환경 테이블에서 라이브로 FK 제약 조건을 만들려는 경우 동적 쿼리 아래에서 실행하십시오 .....

    SELECT 'ALTER TABLE '||OBJ.NAME||' ADD CONSTRAINT '||CONST.NAME||'     FOREIGN KEY ('||COALESCE(ACOL.NAME, COL.NAME)||') REFERENCES '
||ROBJ.NAME ||' ('||COALESCE(RACOL.NAME, RCOL.NAME) ||');'
FROM SYS.CON$ CONST
INNER JOIN SYS.CDEF$ CDEF ON CDEF.CON# = CONST.CON#
INNER JOIN SYS.CCOL$ CCOL ON CCOL.CON# = CONST.CON#
INNER JOIN SYS.COL$ COL  ON (CCOL.OBJ# = COL.OBJ#) AND (CCOL.INTCOL# =     COL.INTCOL#)
INNER JOIN SYS.OBJ$ OBJ ON CCOL.OBJ# = OBJ.OBJ#
LEFT JOIN SYS.ATTRCOL$ ACOL ON (CCOL.OBJ# = ACOL.OBJ#) AND (CCOL.INTCOL# =     ACOL.INTCOL#)

INNER JOIN SYS.CON$ RCONST ON RCONST.CON# = CDEF.RCON#
INNER JOIN SYS.CCOL$ RCCOL ON RCCOL.CON# = RCONST.CON#
INNER JOIN SYS.COL$ RCOL  ON (RCCOL.OBJ# = RCOL.OBJ#) AND (RCCOL.INTCOL# =     RCOL.INTCOL#)
INNER JOIN SYS.OBJ$ ROBJ ON RCCOL.OBJ# = ROBJ.OBJ#
LEFT JOIN SYS.ATTRCOL$ RACOL  ON (RCCOL.OBJ# = RACOL.OBJ#) AND     (RCCOL.INTCOL# = RACOL.INTCOL#)

WHERE CONST.OWNER# = userenv('SCHEMAID')
AND RCONST.OWNER# = userenv('SCHEMAID')
AND CDEF.TYPE# = 4 
AND OBJ.NAME = <table_name>;

1
코드를 조금만 설명해보십시오. 코드를주는 것은 숙제를하는 것과 같습니다.
CoderNeji

1

겸손한 견해로 볼 때 내 버전은 더 읽기 쉽습니다.

SELECT   PARENT.TABLE_NAME  "PARENT TABLE_NAME"
,        PARENT.CONSTRAINT_NAME  "PARENT PK CONSTRAINT"
,       '->' " "
,        CHILD.TABLE_NAME  "CHILD TABLE_NAME"
,        CHILD.COLUMN_NAME  "CHILD COLUMN_NAME"
,        CHILD.CONSTRAINT_NAME  "CHILD CONSTRAINT_NAME"
FROM     ALL_CONS_COLUMNS   CHILD
,        ALL_CONSTRAINTS   CT
,        ALL_CONSTRAINTS   PARENT
WHERE    CHILD.OWNER  =  CT.OWNER
AND      CT.CONSTRAINT_TYPE  = 'R'
AND      CHILD.CONSTRAINT_NAME  =  CT.CONSTRAINT_NAME 
AND      CT.R_OWNER  =  PARENT.OWNER
AND      CT.R_CONSTRAINT_NAME  =  PARENT.CONSTRAINT_NAME 
AND      CHILD.TABLE_NAME  = ::table -- table name variable
AND      CT.OWNER  = ::owner; -- schema variable, could not be needed

1
그것을 작동하게하기 위해, 나는 변경했다 :::table함께tabl
ZygD

예,있는 거 rigth를, 나는 그것이 WinSQL 및 변수 인식 사용을 사용하여 만든 :: 대신 : , 만 사용해야합니다 SQLDeveloper,처럼 : 변수로 텍스트를주의하는. 명확하지 않으면 죄송합니다.
Francisco M

1

답변에 약간 늦었지만 내 대답이 복합 외래 키를 선택 해야하는 사람에게 유용하기를 바랍니다.

SELECT
    "C"."CONSTRAINT_NAME",
    "C"."OWNER" AS "SCHEMA_NAME",
    "C"."TABLE_NAME",
    "COL"."COLUMN_NAME",
    "REF_COL"."OWNER" AS "REF_SCHEMA_NAME",
    "REF_COL"."TABLE_NAME" AS "REF_TABLE_NAME",
    "REF_COL"."COLUMN_NAME" AS "REF_COLUMN_NAME"
FROM
    "USER_CONSTRAINTS" "C"
INNER JOIN "USER_CONS_COLUMNS" "COL" ON "COL"."OWNER" = "C"."OWNER"
 AND "COL"."CONSTRAINT_NAME" = "C"."CONSTRAINT_NAME"
INNER JOIN "USER_CONS_COLUMNS" "REF_COL" ON "REF_COL"."OWNER" = "C"."R_OWNER"
 AND "REF_COL"."CONSTRAINT_NAME" = "C"."R_CONSTRAINT_NAME"
 AND "REF_COL"."POSITION" = "COL"."POSITION"
WHERE "C"."TABLE_NAME" = 'TableName' AND "C"."CONSTRAINT_TYPE" = 'R'

1

나는 아래 코드를 사용했고 그것은 내 목적을 달성했다.

SELECT fk.owner, fk.table_name, col.column_name
FROM dba_constraints pk, dba_constraints fk, dba_cons_columns col
WHERE pk.constraint_name = fk.r_constraint_name
AND fk.constraint_name = col.constraint_name
AND pk.owner = col.owner
AND pk.owner = fk.owner
AND fk.constraint_type = 'R'   
AND pk.owner = sys_context('USERENV', 'CURRENT_SCHEMA') 
AND pk.table_name = :my_table
AND pk.constraint_type = 'P';

0
select d.table_name,

       d.constraint_name "Primary Constraint Name",

       b.constraint_name "Referenced Constraint Name"

from user_constraints d,

     (select c.constraint_name,

             c.r_constraint_name,

             c.table_name

      from user_constraints c 

      where table_name='EMPLOYEES' --your table name instead of EMPLOYEES

      and constraint_type='R') b

where d.constraint_name=b.r_constraint_name

솔루션에서 수행 한 작업을 작성하십시오. 감사합니다.
Leonid Glanz

@LeonidGlanz, 그것은 '테이블 이름'을 제외 하고 내 솔루션에서 한 것과 동일합니다. 무슨 말인지 이해가 안됩니다 ...
ALIRA

1
필요에 따라 user_constraints를 변경할 수 있습니다 all_constraints.
ALIRA

또한 테이블 이름이 고려되는 where 절을 제거 할 수 있습니다.
ALIRA

constraint_type = 'R'은 구속 조건을 필터링하여 관계 구속 조건 만 표시합니다.
ALIRA

0
SELECT a.table_name, a.column_name, a.constraint_name, c.owner, 
       -- referenced pk
       c.r_owner, c_pk.table_name r_table_name, c_pk.constraint_name r_pk
  FROM all_cons_columns a
  JOIN all_constraints c ON a.owner = c.owner
                        AND a.constraint_name = c.constraint_name
  JOIN all_constraints c_pk ON c.r_owner = c_pk.owner
                           AND c.r_constraint_name = c_pk.constraint_name
 WHERE c.constraint_type = 'R'
   AND a.table_name :=TABLE_NAME
   AND c.owner :=OWNER_NAME;

0
WITH reference_view AS
     (SELECT a.owner, a.table_name, a.constraint_name, a.constraint_type,
             a.r_owner, a.r_constraint_name, b.column_name
        FROM dba_constraints a, dba_cons_columns b
       WHERE  a.owner LIKE UPPER ('SYS') AND
          a.owner = b.owner
         AND a.constraint_name = b.constraint_name
         AND constraint_type = 'R'),
     constraint_view AS
     (SELECT a.owner a_owner, a.table_name, a.column_name, b.owner b_owner,
             b.constraint_name
        FROM dba_cons_columns a, dba_constraints b
       WHERE a.owner = b.owner
         AND a.constraint_name = b.constraint_name
         AND b.constraint_type = 'P'
         AND a.owner LIKE UPPER ('SYS')
         )
SELECT  
       rv.table_name FK_Table , rv.column_name FK_Column ,
       CV.table_name PK_Table , rv.column_name PK_Column , rv.r_constraint_name Constraint_Name 
  FROM reference_view rv, constraint_view CV
 WHERE rv.r_constraint_name = CV.constraint_name AND rv.r_owner = CV.b_owner;

0

UserTable로드 (외래 키 및 참조하는 테이블 목록)

WITH

reference_view AS
     (SELECT a.owner, a.table_name, a.constraint_name, a.constraint_type,
             a.r_owner, a.r_constraint_name, b.column_name
        FROM dba_constraints a, dba_cons_columns b
       WHERE 
          a.owner = b.owner
         AND a.constraint_name = b.constraint_name
         AND constraint_type = 'R'),
constraint_view AS
     (SELECT a.owner a_owner, a.table_name, a.column_name, b.owner b_owner,
             b.constraint_name
        FROM dba_cons_columns a, dba_constraints b
       WHERE a.owner = b.owner
         AND a.constraint_name = b.constraint_name
         AND b.constraint_type = 'P'

         ) ,
usertableviewlist AS 
(
      select  TABLE_NAME  from user_tables  
) 
SELECT  
       rv.table_name FK_Table , rv.column_name FK_Column ,
       CV.table_name PK_Table , rv.column_name PK_Column , rv.r_constraint_name Constraint_Name 
  FROM reference_view rv, constraint_view CV , usertableviewlist UTable
 WHERE rv.r_constraint_name = CV.constraint_name AND rv.r_owner = CV.b_owner And UTable.TABLE_NAME = rv.table_name; 
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.