2010-03-31 55 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;