web-dev-qa-db-ja.com

Oracleのすべてのユーザーテーブル/シーケンスを削除する

ビルドプロセスと進化するデータベースの一部として、ユーザーのすべてのテーブルとシーケンスを削除するスクリプトを作成しようとしています。許可されているよりも多くのアクセス許可が必要になるため、ユーザーを再作成したくありません。

私のスクリプトは、テーブル/シーケンスを削除するプロシージャを作成し、プロシージャを実行してから、プロシージャを削除します。私はsqlplusからファイルを実行しています:

drop.sql:


create or replace procedure drop_all_cdi_tables
is
cur integer;
begin
cur:= dbms_sql.OPEN_CURSOR();
for t in (select table_name from user_tables) loop
execute immediate 'drop table ' ||t.table_name|| ' cascade constraints';
end loop;
dbms_sql.close_cursor(cur);

cur:= dbms_sql.OPEN_CURSOR();
for t in (select sequence_name from user_sequences) loop
execute immediate 'drop sequence ' ||t.sequence_name;
end loop;
dbms_sql.close_cursor(cur);
end;
/
execute drop_all_cdi_tables;
/
drop procedure drop_all_cdi_tables;
/

残念ながら、プロシージャを削除すると問題が発生します。競合状態が発生しているようで、プロシージャは実行前に削除されます。
例えば。:

 SQL * Plus:リリース11.1.0.7.0-2010年3月30日火曜日18:45:42に本番運用[2010年..____。] 
 Copyright(c)1982、2008、Oracle。 
 
 
接続先:
 Oracle Database 11g Enterprise Editionリリース11.1.0.7.0-64ビット実動
パーティション化により、 OLAP、データマイニング、およびReal Application Testingオプション
 
 
プロシージャが作成されました。
 
 
 PL/SQLプロシージャが正常に完了しました。
 
 
プロシージャが作成されました。
 
 
プロシージャがドロップされました。
 
ドロッププロシージャdrop_all_user_tables 
 * 
 1行目のエラー:
 ORA-04043:オブジェクトDROP_ALL_USER_TABLESは存在しません
 
 
 SQL> Oracle Database 11gから切断Enterprise Editionリリース11.1.0.7.0-64 
パーティショニング、OLAP、データマイニング、およびReal Application Testingオプション

これを機能させる方法についてのアイデアはありますか?

31
Ambience

ストアドプロシージャを保持するつもりがない場合は、 匿名PLSQLブロック を使用します。

BEGIN

  --Bye Sequences!
  FOR i IN (SELECT us.sequence_name
              FROM USER_SEQUENCES us) LOOP
    EXECUTE IMMEDIATE 'drop sequence '|| i.sequence_name ||'';
  END LOOP;

  --Bye Tables!
  FOR i IN (SELECT ut.table_name
              FROM USER_TABLES ut) LOOP
    EXECUTE IMMEDIATE 'drop table '|| i.table_name ||' CASCADE CONSTRAINTS ';
  END LOOP;

END;
77
OMG Ponies

SQLステートメントの場合、末尾のセミコロンがステートメントを実行します。 /は前のステートメントを実行します。そのため、次の行を終了します

drop procedure drop_all_cdi_tables;
/

プロシージャをドロップしてから、もう一度ドロップしてみます。

出力を見ると、「PROCEDURE CREATED」が表示され、実行され、最後のステートメントが再実行されるため「PROCEDURE CREATED」が再び表示されます(EXECUTEはステートメントではなくSQL * Plusコマンドであり、バッファリングされません) )、次に「PROCEDURE DROPPED」を選択し、2回目にドロップしようとします(そして失敗します)。

PS。奇妙なDBMS_SQL呼び出しについてはDougmanに同意します。

6
Gary Myers

例のエラーメッセージはdrop_all_user_tablesでエラーを受け取っているようですが、指定した例はdrop_all_cdi_tablesのものです。 drop_all_user_tablesコードは異なって見えますか?

また、dbms_sqlへの呼び出しがありますが、それを使用して解析を行っていないようです。

2
Doug Porter

OMG Poniesが提供するソリューションに加えて、空白スペースを含むシーケンスがある場合は、PLSQLを少し強化する必要があります。

BEGIN
  FOR i IN (SELECT sequence_name FROM user_sequences)
    Loop
      EXECUTE IMMEDIATE('"DROP SEQUENCE ' || user || '"."' || i.sequence_name || '"');
    End Loop;
End;
/
1
bravenoob

何らかの理由で、OMG PoniesソリューションがPLSQLで「SQLコマンドが正しく終了しませんでした」というエラーを出しました。他の誰かが同じ問題に遭遇した場合に備えて、現在のスキーマのすべてのテーブルを削除する方法を次に示します。

DECLARE
  table_name VARCHAR2(30);
  CURSOR usertables IS SELECT * FROM user_tables WHERE table_name NOT LIKE 'BIN$%';
BEGIN
  FOR i IN usertables
  LOOP
  EXECUTE IMMEDIATE 'drop table ' || i.table_name || ' cascade constraints';
  END LOOP;
END;
/

クレジット: Snippler

0
ZerosAndOnes

これらの2つのステートメントを実行してから、すべての結果を実行します。

select 'drop table ' || table_name || ';' from user_tables;
select 'drop sequence ' || sequence_name || ';' from user_sequences;
0
Ahmed Elgamal