对于我的应用程序,我需要检索某个数据库模式的所有表的主键列,不包括那些也是外键的列。
换句话说,如果一个 M:N 关系表不使用自己的主键,而是使用两个外键的组合作为主键,则应排除这些列。
现在可以使用以下语句轻松完成第一部分:
SELECT ac.table_name,
acc.column_name
FROM all_constraints ac,
all_cons_columns acc
WHERE ac.constraint_name = acc.constraint_name
AND ac.constraint_type = 'P'
AND ac.owner = UPPER('MY_SCHEMA')
ORDER BY ac.table_name, acc.position
对于我的情况,执行此操作大约需要 0.2 秒。现在我尝试使用以下添加排除组合外键:
AND NOT EXISTS(
SELECT 1
FROM all_constraints ac1, all_cons_columns acc1
WHERE ac1.constraint_name = acc1.constraint_name
AND ac1.owner = ac.owner
AND ac1.table_name = ac.table_name
AND acc1.column_name = acc.column_name
AND ac1.constraint_type = 'R'
)
现在执行整个语句大约需要 2.5 秒。
有没有更有效的方法来获得相同的结果?
我总是可以执行两个单独的查询,将结果放入列表中并从代码中的列表 1 中删除列表 2 的条目,但我更喜欢使用单语句解决方案。
为了使这个问题不那么主观,我将制定以下规则:
- 我会赞成任何我认为有帮助的答案(我总是这样做)
- 我会接受使执行时间低于一秒的第一个答案
PS:我正在使用Oracle 10g
并且该语句是从使用的.NET
应用程序执行的Oracle.DataAccess.dll
,但我从SqlDeveloper
.
解决方案:
根据 Don Bracuk 的回答,我设法使用以下语句将执行时间缩短到 120 毫秒左右:
SELECT table_name, column_name
FROM
(
SELECT ac.table_name, acc.column_name
FROM all_constraints ac, all_cons_columns acc
WHERE ac.constraint_type = 'P'
AND ac.owner = UPPER('my_schema')
-- if you wondered, "UPPER" is used as 'my_schema' is inserted at runtime
MINUS
SELECT ac1.table_name, acc1.column_name
FROM all_constraints ac1, all_cons_columns acc1
WHERE ac1.constraint_type = 'P'
AND ac1.owner = UPPER('my_schema')
)
ORDER BY table_name;