2010-03-31 24 views
27

Como parte de nuestro proceso de construcción y base de datos en evolución, estoy tratando de crear un script que eliminará todas las tablas y secuencias para un usuario. No quiero volver a crear el usuario ya que esto requerirá más permisos de los permitidos.todos los usuarios mesas/secuencias en Oracle

Mi secuencia de comandos crea un procedimiento para eliminar las tablas/secuencias, ejecuta el procedimiento y luego descarta el procedimiento. Estoy ejecutando el archivo de 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; 
/

Desafortunadamente, dejando caer el procedimiento causa un problema. Parece que causa una condición de carrera y el procedimiento se descarta antes de que se ejecute.
ej .:

 
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 

¿Alguna idea sobre cómo conseguir este trabajo?

Respuesta

69

Si no está con la intención de mantener el procedimiento almacenado, que haría uso de 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 esto. no es necesario crear el procedimiento –

+0

Esto hace el truco. Curiosamente, tuve que agregar un final/al final del script para ejecutar realmente el bloque PLSQL anónimo.Si luego creamos una tarea MSBUILD personalizada para ejecutar las instrucciones en el script, ¿causarán/causarán problemas? – Ambience

+0

El/dice sqlplus que su bloque PLSQL está hecho, y para enviarlo a la base de datos para su procesamiento. Entonces, si su MSBUILD usa sqlplus necesitará el /. –

2

Parece que el mensaje de error de ejemplo está recibiendo un error en drop_all_user_tables pero el ejemplo que dio es para drop_all_cdi_tables. ¿El código drop_all_user_tables tiene un aspecto diferente?

También tiene llamadas al dbms_sql pero parece que no las está usando para realizar ningún análisis sintáctico.

+0

Drop_all_cdi_tables es el mismo código. El dbms_sql fue tomado de otro ejemplo: soy un principiante de P/L SQL :) – Ambience

6

Para una sentencia SQL, el punto y coma al final va a ejecutar la instrucción. El/ejecutará la declaración anterior. Como tal, se termina líneas de

drop procedure drop_all_cdi_tables; 
/

bajarán el procedimiento, a continuación, tratar de dejarlo caer de nuevo.

Si mira su resultado, verá 'PROCEDIMIENTO CREADO', luego se ejecutará, luego 'PROCEDIMIENTO CREADO' de nuevo, ya que vuelve a ejecutar la última instrucción (EJECUTAR es un comando SQL * Plus, no una declaración tan no está almacenado en el búfer) luego "PROCEDURE DROPPED" y luego intenta (y falla) soltarlo por segunda vez.

PS. Estoy de acuerdo con Dougman en las extrañas llamadas DBMS_SQL.

0

Además de la solución presentada por OMG de los potros, si tiene secuencias con espacios en blanco, lo que necesita para mejorar la PLSQL un poco:

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

Por alguna razón solución de OMG potros dio un error "comando SQL no terminado correctamente "en PLSQL. En caso de que alguien más se encuentre con el mismo problema, así es como pude eliminar todas las tablas en el esquema actual.

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

Créditos: Snippler

0

Sólo tiene que ejecutar estas dos declaraciones y luego ejecutar todos los resultados:

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