22

私は非常に大規模なOracleデータベースを持っており、多くのテーブルと数百万の行があります。それらの1つを削除する必要がありますが、それを削除しても、外部キーレコードとしてそれを指す他の依存行が壊れないことを確認したいと思います。この行を指す他のすべてのレコード、または少なくともテーブルスキーマのリストを取得する方法はありますか?自分で削除して例外をキャッチできることはわかっていますが、スクリプトを自分で実行することはなく、最初からクリーンに実行する必要があります。

OracleのSQLDeveloperツールとAllRoundAutomationsのPL/SQLDeveloperツールを自由に使用できます。

前もって感謝します!

4

7 に答える 7

36

テーブルへのすべての参照をリストする私の解決策は次のとおりです。

select
  src_cc.owner as src_owner,
  src_cc.table_name as src_table,
  src_cc.column_name as src_column,
  dest_cc.owner as dest_owner,
  dest_cc.table_name as dest_table,
  dest_cc.column_name as dest_column,
  c.constraint_name
from
  all_constraints c
inner join all_cons_columns dest_cc on
  c.r_constraint_name = dest_cc.constraint_name
  and c.r_owner = dest_cc.owner
inner join all_cons_columns src_cc on
  c.constraint_name = src_cc.constraint_name
  and c.owner = src_cc.owner
where
  c.constraint_type = 'R'
  and dest_cc.owner = 'MY_TARGET_SCHEMA'
  and dest_cc.table_name = 'MY_TARGET_TABLE'
  --and dest_cc.column_name = 'MY_OPTIONNAL_TARGET_COLUMN'
;

このソリューションを使用すると、どのテーブルのどの列がターゲット テーブルのどの列を参照しているかという情報も得られます (また、それをフィルター処理できます)。

于 2012-10-02T09:14:39.580 に答える
28

私は常に開始テーブルの外部キーを見て、元に戻ります。DB ツールには通常、依存関係または制約ノードがあります。PL/SQL DeveloperにはFKを表示する方法があることは知っていますが、それを使用してからしばらく経っているため、説明できません...

XXXXXXXXXXXX をテーブル名に置き換えるだけです...

/* The following query lists all relationships */ 

select
 a.owner||'.'||a.table_name "Referenced Table"
,b.owner||'.'||b.table_name "Referenced by"
,b.constraint_name "Foreign Key"
from all_constraints a, all_constraints b 
where 
b.constraint_type = 'R'
and a.constraint_name = b.r_constraint_name 
and b.table_name='XXXXXXXXXXXX' -- Table name 
order by a.owner||'.'||a.table_name
于 2010-03-24T17:01:57.590 に答える
12

私は最近同様の問題を抱えていましたが、直接の依存関係を見つけるだけでは不十分であることをすぐに経験しました。そこで、マルチレベルの外部キー依存関係のツリーを表示するクエリを作成しました。

SELECT LPAD(' ',4*(LEVEL-1)) || table1 || ' <-- ' || table2 tables, table2_fkey
FROM
  (SELECT a.table_name table1, b.table_name table2, b.constraint_name table2_fkey
  FROM user_constraints a, user_constraints b 
  WHERE a.constraint_type IN('P', 'U') 
  AND b.constraint_type = 'R' 
  AND a.constraint_name = b.r_constraint_name 
  AND a.table_name != b.table_name
  AND b.table_name <> 'MYTABLE')
CONNECT BY PRIOR  table2 = table1 AND LEVEL <= 5
START WITH table1 = 'MYTABLE';

データベースでSHIPMENTをMYTABLEとして使用すると、次のような結果が得られます。

SHIPMENT <-- ADDRESS
SHIPMENT <-- PACKING_LIST
    PACKING_LIST <-- PACKING_LIST_DETAILS
    PACKING_LIST <-- PACKING_UNIT
        PACKING_UNIT <-- PACKING_LIST_ITEM
    PACKING_LIST <-- PO_PACKING_LIST
...
于 2014-02-13T19:35:04.770 に答える
3

データ ディクショナリを使用して、問題のテーブルの主キーを参照するテーブルを特定できます。そこから動的 SQL を生成して、それらのテーブルにザップしたい値を問い合わせることができます。

SQL> declare
  2      n pls_integer;
  3      tot pls_integer := 0;
  4  begin
  5      for lrec in ( select table_name from user_constraints
  6                    where r_constraint_name = 'T23_PK' )
  7      loop
  8          execute immediate 'select count(*) from '||lrec.table_name
  9                              ||' where col2 = :1' into n using &&target_val;
 10          if n = 0 then
 11              dbms_output.put_line('No impact on '||lrec.table_name);
 12          else
 13              dbms_output.put_line('Uh oh! '||lrec.table_name||' has '||n||' hits!');
 14          end if;
 15          tot := tot + n;
 16      end loop;
 17      if tot = 0
 18      then
 19          delete from t23 where col2 = &&target_val;
 20          dbms_output.put_line('row deleted!');
 21      else
 22          dbms_output.put_line('delete aborted!');
 23      end if;
 24  end;
 25  /
Enter value for target_val: 6
No impact on T34
Uh oh! T42 has 2 hits!
No impact on T69
delete aborted!

PL/SQL procedure successfully completed.

SQL>

この例は少しごまかしています。ターゲット主キーの名前はハードコーディングされており、参照列はすべての従属テーブルで同じ名前になっています。これらの問題の修正は、読者の課題として残されています ;)

于 2010-03-24T17:26:55.720 に答える
0

外部キー関係に基づいてテーブルの依存関係の順序を見つけるのがいかに難しいかに驚きました。すべてのテーブルからデータを削除して再度インポートしたかったので、必要でした。以下は、テーブルを依存関係順にリストするために作成したクエリです。以下のクエリを使用して削除のスクリプトを作成し、クエリの結果を逆の順序で使用して再度インポートすることができました。

   SELECT referenced_table
         ,MAX(lvl) for_deleting
         ,MIN(lvl) for_inserting
   FROM
         ( -- Hierarchy of dependencies
         SELECT LEVEL lvl
               ,t.table_name referenced_table
               ,b.table_name referenced_by
         FROM user_constraints A
         JOIN user_constraints b 
               ON  A.constraint_name = b.r_constraint_name
               and b.constraint_type = 'R'
         RIGHT JOIN user_tables t
               ON  t.table_name = A.table_name
         START WITH b.table_name IS NULL
         CONNECT BY b.table_name = PRIOR t.table_name
         )
   GROUP BY referenced_table
   ORDER BY for_deleting, for_inserting;
于 2015-06-18T05:58:02.503 に答える