2010-03-31 10 views
27

Dans le cadre de notre processus de génération et de l'évolution de la base de données, j'essaie de créer un script qui supprimera toutes les tables et séquences d'un utilisateur. Je ne veux pas faire recréer l'utilisateur car cela nécessitera plus d'autorisations que permis.Suppression de toutes les tables/séquences utilisateur dans Oracle

Mon script crée une procédure pour supprimer les tables/séquences, exécute la procédure, puis supprime la procédure. Je l'exécution du fichier 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; 
/

Malheureusement, laissant tomber la procédure pose un problème. Il semble provoquer une condition de concurrence et la procédure est abandonnée avant son exécution.
.: par exemple

 
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 

Toutes les idées sur la façon d'obtenir ce travail?

Répondre

69

Si vous n'êtes pas l'intention de garder la procédure stockée, j'utiliser 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 ceci. pas besoin de créer la procédure –

+0

Cela fait l'affaire. Bizarrement, j'ai dû ajouter une fin/à la fin du script pour exécuter le bloc PLSQL anonyme.Si nous créons plus tard une tâche MSBUILD personnalisée pour exécuter des instructions dans le script, est-ce que/causera des problèmes? – Ambience

+0

Le/dit à sqlplus que votre bloc PLSQL est terminé, et de le soumettre à la base de données pour traitement. Donc, si votre MSBUILD utilise sqlplus, il aura besoin de /. –

2

Il ressemble à votre exemple un message d'erreur est d'obtenir une erreur sur drop_all_user_tables mais l'exemple que vous avez donné est pour drop_all_cdi_tables. Est-ce que le code drop_all_user_tables est différent?

Vous avez également des appels à dbms_sql mais ne semblez pas l'utiliser pour effectuer une analyse.

+0

drop_all_cdi_tables est le même code. Le dbms_sql a été emprunté à un autre exemple - je suis un P/L SQL novice :) – Ambience

6

Pour une instruction SQL, le point-virgule à la fin exécutera l'instruction. Le/exécutera l'instruction précédente. En tant que tel, vous finissez par des lignes de

drop procedure drop_all_cdi_tables; 
/

baisseront la procédure, puis essayez de le déposer à nouveau. Si vous regardez votre sortie, vous verrez 'PROCEDURE CREATED', puis exécuté, puis 'PROCEDURE CREATED' à nouveau lors de la ré-exécution de la dernière instruction (EXECUTE est une commande SQL * Plus, pas une instruction n'est pas tamponné) alors "PROCEDURE REJETÉE" et alors il essaye (et échoue) de le laisser tomber la deuxième fois.

PS. Je suis d'accord avec Dougman sur les appels DBMS_SQL impairs.

0

En plus de la solution présentée par OMG Ponies, si vous avez des séquences avec des espaces vides, vous devez améliorer le PLSQL un peu:

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

Pour une raison quelconque solution Poneys OMG a une erreur « commande SQL pas correctement terminé "sur PLSQL. Dans le cas où quelqu'un d'autre rencontre le même problème, voici comment j'ai été capable de supprimer toutes les tables dans le schéma actuel.

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édits: Snippler

0

il suffit d'exécuter ces deux déclarations, puis exécutez tous les résultats:

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