私のアプリケーションでは、外部キーでもある列を除いて、特定のデータベース スキーマのすべてのテーブルの主キー列を取得する必要があります。
つまり、M:N 関係テーブルが独自の主キーを使用せず、2 つの外部キーの組み合わせを主キーとして使用する場合、それらの列は除外されます。
最初の部分は、次のステートメントを使用して簡単に実行できます。
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 秒かかります。
同じ結果を得るより効率的な方法はありますか?
私はいつでも 2 つの別々のクエリを実行し、結果をリストに入れ、コードでリスト 1 からリスト 2 のエントリを削除することができましたが、単一のステートメント ソリューションを使用したいと考えています。
この質問を主観的でなくするために、次のルールがあります。
- 役立つと思われる回答に賛成します(私はいつもそうします)
- 実行時間を 1 秒未満にする最初の回答を受け入れます
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;