2010-03-31 53 views
27

作为我们构建过程和不断发展的数据库的一部分,我试图创建一个脚本,它将删除用户的所有表和序列。我不想重新创建用户,因为这需要比允许的更多权限。删除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: 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 

如何得到这个工作任何想法?

回答

69

如果你不保持存储过程的打算,我会使用一个anonymous PLSQL block

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; 
+0

+1。不需要创建程序 – 2010-03-31 01:59:15

+0

这是诀窍。奇怪的是,我不得不在脚本末尾添加尾部/以实际执行匿名PLSQL块。如果我们稍后创建一个自定义的MSBUILD任务来执行脚本中的语句 - 会导致/导致问题? – Ambience 2010-03-31 15:10:32

+0

/告诉sqlplus您的PLSQL块已完成,并将其提交给数据库进行处理。所以如果你的MSBUILD使用sqlplus,它将需要/。 – 2010-03-31 15:55:28

2

它看起来像你的榜样错误消息得到一个错误的drop_all_user_tables但你给的例子是drop_all_cdi_tablesdrop_all_user_tables代码看起来不同吗?

你也打电话给dbms_sql,但似乎没有使用它做任何解析。

+0

drop_all_cdi_tables是相同的代码。 dbms_sql是从另一个例子中借用的 - 我是一个P/L SQL新手:) – Ambience 2010-03-31 15:12:46

6

对于SQL语句,最后的分号将执行该语句。 /将执行前面的语句。 因此,你最终的

drop procedure drop_all_cdi_tables; 
/

线将删除过程,然后再次尝试将其删除。

如果你看看你的输出,你会看到'PROCEDURE CREATED',然后执行,然后'PROCEDURE CREATED'再次执行最后一条语句(EXECUTE是SQL * Plus命令,而不是语句没有缓冲),然后“PROCEDURE DROPPED”,然后尝试(并失败)第二次放弃它。

PS。我同意Dougman对奇数DBMS_SQL的调用。

0

除了由OMG小马提出的解决方案,如果您有空格序列,你需要增强PLSQL了一下:

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

出于某种原因,OMG小马的解决方案给了一个错误“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

0

只要运行这两个语句,然后运行所有的结果:

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