2009-05-09 9 views
17

Estoy tratando de usar un procedimiento (sin parámetros) para descartar todos los objetos de base de datos creados por el usuario ubicados dentro del esquema desde el que se inició el procedimiento, pero estoy realmente no estoy seguro de cómo hacerlo. Esto es lo que tengo hasta ahora, pero creo que estoy haciendo esto de la manera incorrecta.PLSQL - Eliminar todos los objetos de base de datos de un usuario

 

create or replace procedure CLEAN_SCHEMA is 
cursor schema_cur is 
select 'drop '||object_type||' '|| object_name|| DECODE(OBJECT_TYPE,'TABLE',' CASCADE CONSTRAINTS;',';') 
from user_objects; 
schema_rec schema_cur%rowtype; 
begin 
select 'drop '||object_type||' '|| object_name|| DECODE(OBJECT_TYPE,'TABLE',' CASCADE CONSTRAINTS;',';') 
into schema_rec 
from user_objects; 
end; 
/
 
+0

Vaya !!! ¿No te disparas? Es posible que CLEAN_SCHEMA aparezca en el cursor para eliminarlo. – Guru

Respuesta

2

A menos que el usuario tenga permisos difíciles de volver a aplicar, probablemente sea más fácil simplemente soltar al usuario y volver a crearlos.

+0

Dejar caer al usuario no es una opción en este momento. – NMan

1

Lo que tienes es un buen comienzo.

Aquí está el resto:

  • Usted tiene un cursor y una instrucción de selección. Solo necesitas el cursor
  • El siguiente paso es llamar a la declaración de soltar utilizando PLSQL dinámico. Usaría la declaración EXECUTE INMEDIATA. Es más elegante y amigable con el rendimiento, simplemente selecciona el nombre de lo que estás dejando caer y lo envía como una variable de vinculación para EJECUTAR INMEDIATO.
  • Para descartar los objetos del esquema que llama al método y no al esquema que posee el método, debe usar "AUTHID CURRENT_USER". Ver the Oracle documentation para más información.
  • Otras cosas a los golpes: paquetes, funciones, procedimientos (el sistema es probable que cuelgue a continuación, el tiempo de espera si intenta quitar este método, mientras que su ejecución), las clases Java, triggers, vistas, tipos

Por último, esta es obviamente un método muy peligroso, por lo que es posible que desee considerar ponerlo en una secuencia de comandos en lugar de un procedimiento almacenado para que no quede en la base de datos para que nadie la ejecute.

1

Estás cerca, como alguien más ha notado que necesitas un "EJECUTAR INMEDIATO" para la declaración. Usted debe considerar:

  • En lugar de crear un procedimiento para ello, ejecute esto como un bloque PL/SQL anónimos por lo que no tiene el problema de tratar de eliminar un procedimiento que se está ejecutando.

  • Agregue una prueba para el tipo de objeto de TABLE y para ese caso modifique la declaración desplegable para incluir la opción de cascada para manejar tablas que son "padres" de otras tablas mediante restricciones de clave externa. Recuerde que probablemente genere la lista de cursores en un orden que no tenga en cuenta las dependencias que bloquearán la caída.

  • También en el tema de dependencias, probablemente sea mejor soltar tablas primero (agregue un DECODE en su cursor que asigna un valor numérico más bajo a este tipo de objeto y ordene el cursor seleccionar por este valor). Si tiene objetos Oracle de tipo TYPE que se usan como tipos de columna en una definición de tabla, la tabla debe soltarse primero.

  • Si usa Oracle Advanced Queuing, los objetos relacionados con esto DEBEN abandonarse con las llamadas a la API del paquete AQ. Aunque puede eliminar las tablas generadas por Oracle para el soporte de colas con una DROP TABLE regular, se encontrará en la posición catch-22 de no poder soltar las colas relacionadas ni agregarlas.Hasta la versión 10g, al menos, ni siquiera se podía descartar el esquema que contiene la base de datos sin poner en un modo especial cuando esta situación existía

13
declare 
    cursor ix is 
    select * 
     from user_objects 
    where object_type in ('TABLE', 'VIEW', 'FUNCTION', 'SEQUENCE'); 
begin 
for x in ix loop 
    execute immediate('drop '||x.object_type||' '||x.object_name); 
end loop; 
end; 
+0

Esto funciona para mí – Ewerton

+0

informe rror: ORA-00933: comandos SQL no terminó correctamente ORA-06512: en la línea 8 00933. 00000 - "comandos SQL no terminó correctamente" – Suyash

+0

Sólo una observación: Para hacer que funcione con el Tipo "JAVA SOURCE", se debe citar dos veces el nombre_objeto, ya que pueden contener caracteres especiales que deben citarse (p. Ej.,/2bbec77c_JsonEncoding). Además de esta pequeña (pero necesaria) modificación, funciona genial. ¡Gracias! – ddevienne

18
create or replace 
FUNCTION    DROP_ALL_SCHEMA_OBJECTS RETURN NUMBER AS 
PRAGMA AUTONOMOUS_TRANSACTION; 
cursor c_get_objects is 
    select object_type,'"'||object_name||'"'||decode(object_type,'TABLE' ,' cascade constraints',null) obj_name 
    from user_objects 
    where object_type in ('TABLE','VIEW','PACKAGE','SEQUENCE','SYNONYM', 'MATERIALIZED VIEW') 
    order by object_type; 
cursor c_get_objects_type is 
    select object_type, '"'||object_name||'"' obj_name 
    from user_objects 
    where object_type in ('TYPE'); 
BEGIN 
    begin 
    for object_rec in c_get_objects loop 
     execute immediate ('drop '||object_rec.object_type||' ' ||object_rec.obj_name); 
    end loop; 
    for object_rec in c_get_objects_type loop 
     begin 
     execute immediate ('drop '||object_rec.object_type||' ' ||object_rec.obj_name); 
     end; 
    end loop; 
    end; 
    RETURN 0; 
END DROP_ALL_SCHEMA_OBJECTS; 

Crear la función anterior (DDL autónoma por lo que puede ser llamada a través de una función) a continuación, puedes:

select DROP_ALL_SCHEMA_OBJECTS from dual; 

cuando se quiere retirar todos sus objetos, asegúrese de que usted no trate de dejar caer el proc su ejecución (i no se preocupan por el proc s Es por eso que no tiene procsos o funciones en la lista tipo_objeto)

si quiere dejar todo lo que necesita un bloque anónimo

pero tenía que ser capaz de hacer esto de una herramienta que sólo permitía ANSI SQL (no plsql) por lo tanto, un proceso almacenado.

disfrutar.

+0

Funciona bien, muy bien hecho. –

+0

Vine a aprender cómo eliminar ** una ** función. Voy a repetir lo que aprendí, ya que nadie dice cómo funciona la eliminación. 'execute immediate (string)' p. ej. 'execute immediate ('drop function myStupidFunction')' ~ comprueba los espacios. – Bitterblue

2

Gracias Martin Brambley,

me siento podemos simplificar su respuesta de la siguiente manera.

CREATE OR REPLACE 
procedure DROP_ALL_SCHEMA_OBJECTS AS 
PRAGMA AUTONOMOUS_TRANSACTION; 
cursor c_get_objects is 
    select object_type,'"'||object_name||'"'||decode(object_type,'TABLE' ,' cascade constraints',null) obj_name 
    FROM USER_OBJECTS 
    where object_type in ('TABLE','VIEW','PACKAGE','SEQUENCE','SYNONYM', 'MATERIALIZED VIEW', 'TYPE') 
    order by object_type; 
BEGIN 
    begin 
    for object_rec in c_get_objects loop 
     execute immediate ('drop '||object_rec.object_type||' ' ||object_rec.obj_name); 
    end loop; 
    end; 
END DROP_ALL_SCHEMA_OBJECTS; 

/

execute DROP_ALL_SCHEMA_OBJECTS; 
1

Gracias Martin Brambley y Vijayan Srinivasan!

versión

Pero Vijayan de Srinivasan no es correcta, ya que los objetos dependientes de tipo 'tipo' en algún momento genera errores durante las dejan caer:

ORA-02303: No se puede quitar o reemplazar un tipo con el tipo de mesa o dependientes

Mi versión retiren todos los objetos de esquema con adicional:

  • procedimientos y funciones (drop esperan 'DROP_ALL_SCHEMA_OBJECTS')
  • caída de todos los puestos de trabajo y dbms_jobs
  • caída de todos los db_links
  • no deje caer las tablas anidadas, porque DROPING de tablas anidadas no son compatibles
 
CREATE OR REPLACE 
procedure DROP_ALL_SCHEMA_OBJECTS AS 
PRAGMA AUTONOMOUS_TRANSACTION; 
cursor c_get_objects is 
    select uo.object_type object_type_2,'"'||uo.object_name||'"'||decode(uo.object_type,'TABLE' ,' cascade constraints',null) obj_name2 
    FROM USER_OBJECTS uo 
    where uo.object_type in ('TABLE','VIEW','PACKAGE','SEQUENCE','SYNONYM', 'MATERIALIZED VIEW', 'FUNCTION', 'PROCEDURE') 
     and not (uo.object_type = 'TABLE' and exists (select 1 from user_nested_tables unt where uo.object_name = unt.table_name)) 
     and not (uo.object_type = 'PROCEDURE' and uo.object_name = 'DROP_ALL_SCHEMA_OBJECTS') 
    order by uo.object_type; 
cursor c_get_objects_type is 
    select object_type, '"'||object_name||'"' obj_name 
    from user_objects 
    where object_type in ('TYPE'); 
cursor c_get_dblinks is 
    select '"'||db_link||'"' obj_name 
    from user_db_links; 
cursor c_get_jobs is 
    select '"'||object_name||'"' obj_name 
    from user_objects 
    where object_type = 'JOB'; 
cursor c_get_dbms_jobs is 
    select job obj_number_id 
    from user_jobs 
    where schema_user != 'SYSMAN'; 
BEGIN 
    begin 
    for object_rec in c_get_objects loop 
     execute immediate ('drop '||object_rec.object_type_2||' ' ||object_rec.obj_name2); 
    end loop; 
    for object_rec in c_get_objects_type loop 
     begin 
     execute immediate ('drop '||object_rec.object_type||' ' ||object_rec.obj_name); 
     end; 
    end loop; 
    for object_rec in c_get_dblinks loop 
     execute immediate ('drop database link '||object_rec.obj_name); 
    end loop; 
    for object_rec in c_get_jobs loop 
     DBMS_SCHEDULER.DROP_JOB(job_name => object_rec.obj_name); 
    end loop; 
    commit; 
    for object_rec in c_get_dbms_jobs loop 
     dbms_job.remove(object_rec.obj_number_id); 
    end loop; 
    commit; 
    end; 
END DROP_ALL_SCHEMA_OBJECTS; 

/

execute DROP_ALL_SCHEMA_OBJECTS; 
drop procedure DROP_ALL_SCHEMA_OBJECTS; 

exit; 

Cuestiones relacionadas