2

私のアプリケーションでは、外部キーでもある列を除いて、特定のデータベース スキーマのすべてのテーブルの主キー列を取得する必要があります。
つまり、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;
4

2 に答える 2

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
;
于 2013-08-08T15:24:31.827 に答える