1

次のクエリから生成されたすべての行をスクリプトとして単独で実行する方法を知っている人はいますか?

select 'DROP TABLE '||table_name||' CASCADE CONSTRAINTS;' from user_tables;

私が基本的にやろうとしているのは、DB上のすべてのユーザーテーブルと制約を削除することです(これはoracleです)。得られる出力は正しいですが、コピー/貼り付けせずにすべての行を実行する方法を知りたいです。

また、すべてのテーブル (制約を含む) を削除するより効率的な方法はありますか?

4

4 に答える 4

4
begin
  for i in (select table_name from user_tables)
  loop
    execute immediate ('drop table ' || i.table_name || ' cascade constraints');
  end loop;
end;
/

Justin Caveは優れた点を提起しました。以下は、すべての外部キーが一意の制約ではなく主キーを参照していると仮定して、依存関係の階層の最も外側のブランチから始まるユーザーのスキーマ内にテーブルをドロップします。主キーのないテーブルは最後に削除されます。

begin
  for i in (select parent_table, max(tree_depth) as tree_depth
              from (select parent.table_name as parent_table,
                           child.constraint_name as foreign_key, 
                           child.table_name as child_table,
                           LEVEL AS TREE_DEPTH
                      from (select table_name, constraint_name
                              from USER_constraints
                             where constraint_type = 'P'
                           ) parent 
                           LEFT JOIN
                           (SELECT TABLE_NAME, CONSTRAINT_NAME, 
                                   r_constraint_name
                              FROM USER_CONSTRAINTS
                             WHERE CONSTRAINT_TYPE = 'R') child
                              on parent.constraint_name = 
                                    child.r_constraint_name
                           CONNECT BY NOCYCLE 
                             (PRIOR CHILD.TABLE_NAME = PARENT.TABLE_NAME)
                   UNION
                   select DT.table_name as parent_table,
                          NULL AS FOREIGN_KEY, NULL AS CHILD_TABLE,
                          0 AS TREE_DEPTH
                     FROM USER_TABLES DT
                    WHERE TABLE_NAME NOT IN
                          (SELECT TABLE_NAME
                             FROM USER_CONSTRAINTS
                            WHERE CONSTRAINT_TYPE = 'P')
                   )
             group by parent_table
             order by 2 desc
           )
  loop
    execute immediate ('drop table ' || i.parent_table || 
                       ' cascade constraints');
  end loop;
end;
/
于 2011-04-11T21:11:00.193 に答える
3

迅速で汚い解決策は、次のようなことをすることです

FOR x IN (SELECT * FROM user_tables)
LOOP
  BEGIN
    EXECUTE IMMEDIATE 'DROP TABLE ' || x.table_name || 
                        ' CASCADE CONSTRAINTS';
  EXCEPTION
    WHEN others THEN
      dbms_output.put_line( 'Failed to drop ' || x.table_name ); 
  END;
END LOOP;

すべてのテーブルが削除されるまで、それを何度も実行します。親を参照する外部キーを持つ子テーブルがまだある間は、親テーブルを削除できないため、これには複数のパスが必要です。

よりクリーンなオプションは、データ ディクショナリに対して階層クエリを記述して、子テーブル、それらの子の親、祖父母などを取得し、ツリーをたどって適切なオブジェクトを削除することです。これでエラーは回避できますが、コーディングにはもう少し手間がかかります。

于 2011-04-11T21:14:10.963 に答える
1

execute immediate-生成された文字列を渡します

于 2011-04-11T21:02:51.407 に答える
1

一般に、テーブルを削除する場合は、 truncateステートメントを使用する方が効率的です。

executeimmediateコマンドを使用して動的スクリプトを実行できます

于 2011-04-11T21:04:31.593 に答える