【发布时间】:2013-08-09 23:36:40
【问题描述】:
对于我的应用程序,我需要检索某个数据库模式的所有表的主键列,不包括那些也是外键的列。
也就是说,如果一个 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,该语句是从使用Oracle.DataAccess.dll 的.NET 应用程序执行的,但我从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;
【问题讨论】:
标签: sql performance oracle