2010-03-31 11 views
27

Come parte del nostro processo di compilazione e del database in evoluzione, sto cercando di creare uno script che rimuova tutte le tabelle e le sequenze per un utente. Non voglio ricreare l'utente in quanto richiede più autorizzazioni di quelle consentite.Eliminazione di tutte le tabelle/sequenze utente in Oracle

Il mio script crea una procedura per eliminare le tabelle/sequenze, esegue la procedura e quindi elimina la procedura. Sto eseguendo il file da 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; 
/

Purtroppo, lasciando cadere la procedura causa un problema. Sembra che ci sia una condizione di competizione e la procedura viene abbandonata prima dell'esecuzione.
Es .:

 
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 

Tutte le idee su come ottenere questo lavoro?

risposta

69

Se non avete intenzione sul mantenimento della stored procedure, userei un 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 questo. non c'è bisogno di creare la procedura –

+0

Questo fa il trucco. Stranamente, ho dovuto aggiungere un finale/alla fine dello script per eseguire effettivamente il blocco PLSQL anonimo.Se successivamente creiamo un'attività MSBUILD personalizzata per l'esecuzione di istruzioni nello script, il/causerà problemi? – Ambience

+0

// indica a sqlplus che il blocco PLSQL è stato eseguito e di inviarlo al database per l'elaborazione. Quindi se il tuo MSBUILD usa sqlplus avrà bisogno del /. –

2

Sembra che il messaggio di errore di esempio è sempre un errore sul drop_all_user_tables ma l'esempio che hai dato è per drop_all_cdi_tables. Il codice drop_all_user_tables ha un aspetto diverso?

Inoltre si dispone di chiamate a dbms_sql ma non sembrano utilizzarlo per eseguire l'analisi.

+0

Il drop_all_cdi_tables è lo stesso codice. Il dbms_sql è stato preso in prestito da un altro esempio: sono un novizio di P/L SQL :) – Ambience

6

Per un'istruzione SQL, il punto e virgola alla fine eseguirà l'istruzione. Il/eseguirà l'istruzione precedente. Come tale, si finisce linee di

drop procedure drop_all_cdi_tables; 
/

scenderà la procedura, quindi provare a cadere di nuovo.

Se si guarda l'output, verrà visualizzato 'PROCEDURE CREATED', quindi eseguito, quindi 'PROCEDURE CREATED' di nuovo mentre ri-esegue l'ultima istruzione (EXECUTE è un comando SQL * Plus, non un'istruzione così non viene memorizzato nel buffer), quindi "PROCEDURE DROPPED" e quindi tenta (e non riesce) di rilasciarlo la seconda volta.

PS. Sono d'accordo con Dougman sulle strane chiamate DBMS_SQL.

0

Oltre alla soluzione presentata da OMG Ponies, se si dispone di sequenze con spazi vuoti, è necessario migliorare la PLSQL un po ':

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

Per qualche ragione soluzione OMG pony ha dato un errore "comando SQL non correttamente concluso "su PLSQL. Nel caso in cui qualcun altro incontri lo stesso problema, ecco come sono stato in grado di eliminare tutte le tabelle nello schema corrente.

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

Crediti: Snippler

0

basta eseguire queste due affermazioni e quindi eseguire tutti i risultati:

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