PLSQL - удалить все объекты базы данных пользователя - PullRequest
18 голосов
/ 09 мая 2009

Я пытаюсь использовать процедуру (без параметров) для удаления всех созданных пользователем объектов базы данных, расположенных в схеме, из которой запускается процедура, но я действительно не уверен, как это сделать. Вот что у меня есть, но я думаю, что поступаю неправильно.


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;
/

Ответы [ 7 ]

19 голосов
/ 19 октября 2009
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 ваш бег (меня не волнует процесс, поэтому у меня нет procs или функций в списке object_type)

если вы хотите отбросить все, что вам нужно, анонимный блок

но мне нужно было сделать это с помощью инструмента, который разрешал только ANSI SQL (не PLSQL), следовательно, сохраненный процесс.

Наслаждайтесь.

13 голосов
/ 11 мая 2009
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;
2 голосов
/ 17 января 2013

Спасибо, Мартин Брамбли,

Мне кажется, мы можем упростить ваш ответ следующим образом.

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 голосов
/ 09 мая 2009

Если у пользователя нет проблем с повторным применением разрешений, возможно, проще просто удалить пользователя и воссоздать его.

1 голос
/ 02 марта 2016

Спасибо Мартин Брэмбли и Виджаян Шринивасан !

Но версия Виджаяна Шринивасана неверна, потому что зависимые объекты типа '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
  select uo.object_type object_type_2,'"'||uo.object_name||'"'||decode(uo.object_type,'TABLE' ,' cascade constraints',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' and exists (select 1 from user_nested_tables unt where uo.object_name = unt.table_name))
        and not (uo.object_type = 'PROCEDURE' and uo.object_name = 'DROP_ALL_SCHEMA_OBJECTS')
  order 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
      execute immediate ('drop '||object_rec.object_type_2||' ' ||object_rec.obj_name2);
    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;
    for object_rec in c_get_dblinks loop
        execute immediate ('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;

/

execute DROP_ALL_SCHEMA_OBJECTS;
drop procedure DROP_ALL_SCHEMA_OBJECTS;

exit;

1 голос
/ 10 мая 2009

Вы близки - как кто-то еще заметил, вам нужно "ВЫПОЛНИТЬ НЕМЕДЛЕННО" для заявления. Вы должны рассмотреть:

  • Вместо того, чтобы создавать процедуру для этого, запустите ее как анонимный блок PL / SQL, чтобы у вас не возникало проблем с удалением запущенной процедуры.

  • Добавьте тест для типа объекта TABLE и в этом случае измените оператор drop, включив в него опцию cascade для обработки таблиц, которые являются «родителями» других таблиц через ограничения внешнего ключа. Помните, что вы, вероятно, будете генерировать список курсоров в порядке, который не учитывает зависимости, которые будут блокировать удаление.

  • Также по вопросу о зависимостях, вероятно, лучше сначала отбросить таблицы (добавьте DECODE в вашем курсоре, который назначит более низкое числовое значение этому типу объекта и упорядочите курсор, выбранный по этому значению). Если у вас есть объекты Oracle типа TYPE, которые используются в качестве типов столбцов в определении таблицы, таблица должна быть сначала отброшена.

  • Если вы используете Oracle Advanced Queuing, объекты, связанные с этим, ДОЛЖНЫ быть отброшены с помощью вызовов API пакета AQ. Хотя вы можете отбросить сгенерированные Oracle таблицы для поддержки очередей с помощью обычного DROP TABLE, вы окажетесь в позиции catch-22 и не сможете ни отбросить связанные очереди, ни добавить их обратно. По крайней мере, до версии 10g вы не могли даже удалить содержащую схему, не переводя базу данных в специальный режим, когда существовала такая ситуация

1 голос
/ 09 мая 2009

То, что у тебя есть, - хорошее начало.

Вот остальные:

  • У вас есть курсор и оператор выбора. Вам нужен только курсор.
  • Ваш следующий шаг - вызов оператора drop с использованием динамического PLSQL. Я бы использовал инструкцию EXECUTE IMMEDIATE. Он более элегантен и удобен для исполнения: просто выберите название объекта, который вы отбрасываете, и отправьте его как переменную связывания в EXECUTE IMMEDIATE.
  • Чтобы отбросить объекты схемы, вызывающей метод, а не схему, владеющую методом, вы должны использовать «AUTHID CURRENT_USER». См. документация Oracle для получения дополнительной информации.
  • Другие вещи, которые нужно отбросить: пакеты, функции, процедуры (система, скорее всего, зависнет, затем время ожидания, если вы попытаетесь отбросить этот метод во время его работы), классы Java, триггеры, представления, типы

Наконец, это, очевидно, очень опасный метод, поэтому вы можете подумать о том, чтобы поместить его в сценарий вместо хранимой процедуры, чтобы его не оставили в базе данных для запуска.

...