Oracle:显示外键列

Oracle : display foreign key columns

我有以下查询,它工作正常并产生了这些结果。

我卡住的地方是试图找出用于连接外键的列。

在下面的测试用例中,它应该在 (id) 列中,但如果它是复合键,我喜欢用逗号分隔列表。

我想在 F_KEY 列之后添加此新信息。任何帮助将不胜感激。

我的测试用例:

CREATE TABLE parent 
(
    id NUMBER(10),
    value VARCHAR2(30),

    CONSTRAINT parent_pk PRIMARY KEY (id)
);

CREATE TABLE child
( 
    id NUMBER(10) NOT NULL,
    value NUMBER(10) NOT NULL,

    CONSTRAINT child_pk PRIMARY KEY (id, value),
    CONSTRAINT parent_child_fk
        FOREIGN KEY (id) REFERENCES parent(id)
                ON DELETE CASCADE
);

CREATE TABLE grandchild
( 
    id NUMBER(10) NOT NULL,
    value NUMBER(10) NOT NULL,

    CONSTRAINT grandchild_pk PRIMARY KEY (id, value),
    CONSTRAINT child_grandchild_fk
        FOREIGN KEY (id, value) REFERENCES child (id, value)
                ON DELETE CASCADE
);

WITH f AS
(
    SELECT
        constraint_name, table_name, r_constraint_name
    FROM
        user_constraints
    WHERE
        constraint_type = 'R'
),
p AS 
(
    SELECT
        constraint_name, table_name
    FROM
        user_constraints
    WHERE
        constraint_type = 'P'
),
j (child_table, f_key, parent_table, p_key) AS 
(
    SELECT
        f.table_name, f.constraint_name, p.table_name, f.r_constraint_name
    FROM
        p 
    JOIN
        f ON p.constraint_name = f.r_constraint_name
    UNION ALL
    SELECT
        'PARENT', 
        (SELECT constraint_name 
         FROM p
         WHERE table_name = 'PARENT'), NULL, NULL
    FROM dual
)
SELECT
    level AS lvl, j.*
FROM
    j
START WITH parent_table IS NULL
CONNECT BY nocycle parent_table = prior child_table
ORDER BY lvl, parent_table, child_table;

当前输出

LVL   CHILD_TABLE  F_KEY                PARENT_TABLE    P_KEY
------------------------------------------------------------------
 1    PARENT       PARENT_PK             -               - 
 2    CHILD        PARENT_CHILD_FK       PARENT         PARENT_PK
 3    GRANDCHILD   CHILD_GRANDCHILD_FK   CHILD          CHILD_PK

期望的输出

LVL   CHILD_TABLE  F_KEY              F_COL   PARENT_TABLE    P_KEY
------------------------------------------------------------------------
 1    PARENT       PARENT_PK            -         -             -
 2    CHILD        PARENT_CHILD_FK      ID    PARENT         PARENT_PK
 3    GRANDCHILD   CHILD_GRANDCHILD_FK  ID    CHILD          CHILD_PK

您可以使用 user_cons_columns 字典视图与查询 j 连接,然后通过聚合 LISTAGG() 以连接多个列,例如

WITH f AS
(
    SELECT constraint_name, table_name, r_constraint_name
      FROM user_constraints
     WHERE constraint_type = 'R'
), p AS 
(
    SELECT constraint_name, table_name
      FROM user_constraints
     WHERE constraint_type = 'P'
),j (child_table, f_key, column_name, parent_table, p_key) AS 
(
    SELECT f.table_name, f.constraint_name, c.column_name, 
           p.table_name, f.r_constraint_name
      FROM p
      JOIN f
        ON p.constraint_name = f.r_constraint_name
      LEFT JOIN user_cons_columns c
        ON c.constraint_name = f.constraint_name
    UNION ALL
    SELECT 'PARENT', 
           (SELECT constraint_name 
              FROM p
             WHERE table_name = 'PARENT'), NULL, NULL, NULL
      FROM dual
)
 SELECT MAX(level) AS lvl, child_table, f_key, 
        LISTAGG(column_name,',') WITHIN GROUP (ORDER BY column_name) AS f_key, 
        parent_table, p_key
   FROM j
  START WITH parent_table IS NULL
CONNECT BY nocycle parent_table = prior child_table
GROUP BY child_table, f_key, parent_table, p_key
ORDER BY lvl, parent_table, child_table

Demo