Удаление всех пользовательских таблиц / последовательностей в Oracle - PullRequest
30 голосов
/ 31 марта 2010

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

Мой сценарий создает процедуру для удаления таблиц / последовательностей, выполняет процедуру, а затем отбрасывает процедуру. Я выполняю файл из 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;
/

К сожалению, сброс процедуры вызывает проблему. Кажется, что возникает условие гонки, и процедура отбрасывается до ее выполнения.
E.g.:

 SQL*Plus: Release 11.1.0.7.0 - Production on Tue Mar 30 18:45:42 2010

 Copyright (c) 1982, 2008, Oracle.  All rights reserved.


 Connected to:
 Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 - 64bit Production
 With the Partitioning, OLAP, Data Mining and Real Application Testing options


 Procedure created.


 PL/SQL procedure successfully completed.


 Procedure created.


 Procedure dropped.

 drop procedure drop_all_user_tables
 *
 ERROR at line 1:
 ORA-04043: object DROP_ALL_USER_TABLES does not exist


 SQL> Disconnected from Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 - 64
 With the Partitioning, OLAP, Data Mining and Real Application Testing options

Есть идеи, как заставить это работать?

Ответы [ 6 ]

76 голосов
/ 31 марта 2010

Если вы не собираетесь хранить хранимую процедуру, я бы использовал анонимный блок 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;
6 голосов
/ 31 марта 2010

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

drop procedure drop_all_cdi_tables;
/

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

Если вы посмотрите на свой вывод, вы увидите «PROCEDURE CREATED», затем выполненный, затем «PROCEDURE CREATED» снова, поскольку он повторно выполняет последний оператор (EXECUTE - команда SQL * Plus, а не оператор в буфере), затем "PROCEDURE DROPPED" и затем пытается (и не может) удалить его во второй раз.

PS. Я согласен с Дагманом в нечетных вызовах DBMS_SQL.

2 голосов
/ 31 марта 2010

Похоже, в вашем примере сообщения об ошибке выдается ошибка на drop_all_user_tables, но приведенный вами пример относится к drop_all_cdi_tables. Код drop_all_user_tables выглядит по-другому?

Также у вас есть звонки на dbms_sql, но вы, похоже, не используете его для выполнения какого-либо анализа.

1 голос
/ 01 июня 2015

В дополнение к решению, представленному 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;
/
0 голосов
/ 10 февраля 2018

Просто запустите эти два оператора, а затем запустите все результаты:

select 'drop table ' || table_name || ';' from user_tables;
select 'drop sequence ' || sequence_name || ';' from user_sequences;
0 голосов
/ 24 октября 2016

По какой-то причине решение OMG Ponies выдало ошибку «SQL-команда неправильно завершилась» на PLSQL. В случае, если кто-то еще сталкивается с той же проблемой, вот как я смог удалить все таблицы в текущей схеме.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...