对于我的应用程序,我需要检索某个数据库模式的所有表的主键列,不包括那些也是外键的列。
换句话说,如果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
获得的执行时间几乎相同。< / p>
根据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;
答案 0 :(得分:3)
你可以试试这个结构:
select yourfields
from yourtables
where whatever
and somefield in
(select somefield
fromyourtables
where the conditions are the same as above
minus
select the same field
from whereever
where you want to exclude it)
如果这是我的问题,我认为值得尝试。
答案 1 :(得分:2)
在一个相当大的生产数据库上运行了285毫秒。
SELECT AC.TABLE_NAME
,ACC.COLUMN_NAME
FROM ALL_CONSTRAINTS AC
INNER JOIN
ALL_CONS_COLUMNS ACC
ON AC.CONSTRAINT_NAME = ACC.CONSTRAINT_NAME
LEFT OUTER JOIN
( ALL_CONSTRAINTS AC1
INNER JOIN
ALL_CONS_COLUMNS ACC1
ON AC1.CONSTRAINT_NAME = ACC1.CONSTRAINT_NAME
)
ON AC1.TABLE_NAME = AC.TABLE_NAME
AND ACC1.COLUMN_NAME = ACC.COLUMN_NAME
AND ACC1.OWNER = AC.OWNER
AND AC1.CONSTRAINT_TYPE = 'R'
WHERE AC.CONSTRAINT_TYPE = 'P'
AND AC.OWNER = UPPER('APP_NIKU')
AND AC1.TABLE_NAME IS NULL
ORDER BY AC.TABLE_NAME, ACC.POSITION
;