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
我有以下查询,它工作正常并产生了这些结果。
我卡住的地方是试图找出用于连接外键的列。
在下面的测试用例中,它应该在 (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