web-dev-qa-db-ja.com

PLSQL-ユーザーのすべてのデータベースオブジェクトを削除します

プロシージャ(パラメータなし)を使用して、プロシージャが起動されたスキーマ内にあるユーザー作成のデータベースオブジェクトをすべて削除しようとしていますが、これを実行する方法がよくわかりません。これが私がこれまでに持っているものですが、私はこれについて間違った方法で行っていると思います。


create or replace procedure CLEAN_SCHEMA is
cursor schema_cur is
select 'drop '||object_type||' '|| object_name||  DECODE(OBJECT_TYPE,'TABLE',' CASCADE CONSTRAINTS;',';')
from user_objects;
schema_rec schema_cur%rowtype;
begin
select 'drop '||object_type||' '|| object_name||  DECODE(OBJECT_TYPE,'TABLE',' CASCADE CONSTRAINTS;',';')
into schema_rec
from user_objects;
end;
/
18
NMan
create or replace
FUNCTION                DROP_ALL_SCHEMA_OBJECTS RETURN NUMBER AS
PRAGMA AUTONOMOUS_TRANSACTION;
cursor c_get_objects is
  select object_type,'"'||object_name||'"'||decode(object_type,'TABLE' ,' cascade constraints',null) obj_name
  from user_objects
  where object_type in ('TABLE','VIEW','PACKAGE','SEQUENCE','SYNONYM', 'MATERIALIZED VIEW')
  order by object_type;
cursor c_get_objects_type is
  select object_type, '"'||object_name||'"' obj_name
  from user_objects
  where object_type in ('TYPE');
BEGIN
  begin
    for object_rec in c_get_objects loop
      execute immediate ('drop '||object_rec.object_type||' ' ||object_rec.obj_name);
    end loop;
    for object_rec in c_get_objects_type loop
      begin
        execute immediate ('drop '||object_rec.object_type||' ' ||object_rec.obj_name);
      end;
    end loop;
  end;
  RETURN 0;
END DROP_ALL_SCHEMA_OBJECTS;

上記の関数を作成し(自律型であるため、関数を介してDDLを呼び出すことができます)、次のことができます。

select DROP_ALL_SCHEMA_OBJECTS from dual;

すべてのオブジェクトを削除したい場合は、実行中のprocを削除しようとしないでください(procを気にしないので、object_typeリストにprocまたは関数がありません)

すべてを削除したい場合は、匿名ブロックが必要です

しかし、ansi sql(plsqlではない)のみを許可するツール、つまりストアドプロシージャからこれを実行できる必要がありました。

楽しい。

19
Martin Brambley
declare
  cursor ix is
    select *
      from user_objects
     where object_type in ('TABLE', 'VIEW', 'FUNCTION', 'SEQUENCE');
begin
 for x in ix loop
   execute immediate('drop '||x.object_type||' '||x.object_name);
 end loop;
end;
13
tamla83

ユーザーが権限を再適用するのが難しい場合を除いて、ユーザーを削除して再作成する方がおそらく簡単です。

2
Matthew Watson

Martin Brambleyに感謝します、

私たちはあなたの答えを次のように単純化できると思います。

CREATE OR REPLACE
procedure  DROP_ALL_SCHEMA_OBJECTS AS
PRAGMA AUTONOMOUS_TRANSACTION;
cursor c_get_objects is
  select object_type,'"'||object_name||'"'||decode(object_type,'TABLE' ,' cascade constraints',null) obj_name
  FROM USER_OBJECTS
  where object_type in ('TABLE','VIEW','PACKAGE','SEQUENCE','SYNONYM', 'MATERIALIZED VIEW', 'TYPE')
  order by object_type;
BEGIN
  begin
    for object_rec in c_get_objects loop
      execute immediate ('drop '||object_rec.object_type||' ' ||object_rec.obj_name);
    end loop;
  end;
END DROP_ALL_SCHEMA_OBJECTS;

/

execute DROP_ALL_SCHEMA_OBJECTS;
2

ありがとうMartin BrambleyそしてVijayan Srinivasan

ただし、Vijayan Srinivasanのバージョンは正しくありません。これは、タイプ 'TYPE'の依存オブジェクトが、ドロップ中にエラーを生成することがあるためです。

ORA-02303:型を削除したり、型または表に依存するものに置き換えることはできません

私のバージョンでは、スキーマからすべてのオブジェクトが削除されます。

  • プロシージャと関数を削除します(「DROP_ALL_SCHEMA_OBJECTS」を期待します)
  • すべてのジョブとdbms_jobsを削除します
  • すべてのdb_linksを削除します
  • ネストされたテーブルのドロップはサポートされていないためネストされたテーブルを削除しないでください
 CREATE OR REPLACE 
 procedure DROP_ALL_SCHEMA_OBJECTS AS 
 PRAGMA AUTONOMOUS_TRANSACTION; 
 cursor c_get_objects is 
 selectuo.object。 object_type_2、 '"' || uo.object_name || '"' || decode(uo.object_type、 'TABLE'、 'カスケード制約'、null)obj_name2 
 FROM USER_OBJECTS uo 
 where uo .object_type in( 'TABLE'、 'VIEW'、 'PACKAGE'、 'SEQUENCE'、 'SYNONYM'、 'MATERIALIZED VIEW'、 'FUNCTION'、 'PROCEDURE')
 and not(uo.object_type = ' TABLE 'および存在(user_nested_tables untから1を選択、uo.object_name = unt.table_name))
および存在しない(uo.object_type =' PROCEDURE 'およびuo.object_name =' DROP_ALL_SCHEMA_OBJECTS ')
順序by uo.object_type; 
 cursor c_get_objects_type is 
 select object_type、 '"' || object_name || '"' obj_name 
 from user_objects 
 where object_type in( ' TYPE '); 
 cursor c_get_dblinks is 
 select' "'|| db_link ||'" 'obj_name 
 from user_db_links; 
 cursor c_get_jobs is 
 select '"' || object_name || '"' obj_name 
 from user_objects 
 where object_type = 'JOB'; 
 cursor c_get_dbms_jobs is 
 select job obj_number_id 
 from user_jobs 
 where schema_user!= 'SYSMAN'; 
 BEGIN 
 begin 
 for object_rec in c_get_objects loop 
即時実行( 'drop' || object_rec.object_type_2 || '' || object_rec.obj_name2); 
 end loop; 
 for object_rec in c_get_objects_type loop 
 begin 
即時実行( 'drop' || object_rec.object_type || '' || object_rec.obj_name); 
 end; 
 end loop; 
 for object_rec in c_get_dblinks loop 
即時実行( 'drop database link' || object_rec.obj_name); 
 end loop; 
 for object_rec in c_get_jobs loop 
 DBMS_SCHEDULER.DROP_JOB(job_name => object_rec.obj_name); 
 end loop; 
 commit; 
 for object_rec in c_get_dbms_ jobs loop 
 dbms_job.remove(object_rec.obj_number_id); 
 end loop; 
 commit; 
 end; 
 END DROP_ALL_SCHEMA_OBJECTS; 
 
/
 
 DROP_ALL_SCHEMA_OBJECTS; 
ドロッププロシージャDROP_ALL_SCHEMA_OBJECTS; 
 
 exit; 
 [.____を実行します。 ]
1
xor

あなたは近くにいます-他の誰かがあなたが声明のために「EXECUTEIMMEDIATE」を必要としていると指摘したように。次のことを考慮する必要があります。

  • これを行うためのプロシージャを作成する代わりに、これを匿名のPL/SQLブロックとして実行して、実行中のプロシージャを削除しようとする問題が発生しないようにします。

  • TABLEのオブジェクトタイプのテストを追加し、その場合は、dropステートメントを変更して、外部キー制約を介して他のテーブルの「親」であるテーブルを処理するカスケードオプションを含めます。ドロップをブロックする依存関係を考慮しない順序でカーソルリストを生成する可能性があることに注意してください。

  • また、依存関係については、最初にテーブルを削除するのがおそらく最善です(このオブジェクトタイプに低い数値を割り当てるDECODEをカーソルに追加し、この値でカーソルを選択するように順序付けます)。テーブル定義で列タイプとして使用されるタイプTYPEのOracleオブジェクトがある場合は、最初にテーブルを削除する必要があります。

  • Oracle Advanced Queuingを使用する場合、これに関連するオブジェクトは、AQパッケージAPI呼び出しで削除する必要があります。通常のDROPTABLEを使用してキューサポート用にOracleで生成されたテーブルを削除することはできますが、関連するキューを削除したり、追加し直したりできないというキャッチ22の位置にいることに気付くでしょう。少なくともバージョン10gまでは、この状況が存在する場合、データベースを特別なモードにしないと、含まれているスキーマを削除することさえできませんでした。

1
dpbradley

あなたが持っているものは良いスタートです。

残りは次のとおりです。

  • カーソルとselectステートメントがあります。必要なのはカーソルだけです。
  • 次のステップは、動的PLSQLを使用してdrop文を呼び出すことです。 EXECUTEIMMEDIATEステートメントを使用します。ドロップするものの名​​前を選択し、それをバインド変数としてEXECUTE IMMEDIATEに送信するだけで、よりエレガントでパフォーマンスが向上します。
  • メソッドを所有するスキーマではなく、メソッドを呼び出すスキーマのオブジェクトを削除するには、「AUTHIDCURRENT_USER」を使用する必要があります。詳細については、 Oracleのドキュメント を参照してください。
  • ドロップするその他のもの:パッケージ、関数、プロシージャ(実行中にこのメソッドをドロップしようとすると、システムがハングしてタイムアウトする可能性があります)、Javaクラス、トリガー、ビュー、タイプ

最後に、これは明らかに非常に危険な方法であるため、ストアドプロシージャではなくスクリプトに配置して、誰もが実行できるようにデータベースに残さないようにすることを検討してください。

1
darreljnz