2009-05-09 12 views
17

Próbuję użyć procedury (brak parametrów), aby usunąć wszystkie utworzone przez użytkownika obiekty bazy danych znajdujące się w schemacie, z którego uruchamiana jest procedura, ale ja naprawdę nie wiem, jak to zrobić. Oto, co mam do tej pory, ale myślę, że robię to w niewłaściwy sposób.PLSQL - Upuść wszystkie obiekty bazy danych użytkownika

 

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

Ups !!! Nie strzelasz do siebie? CLEAN_SCHEMA może zostać pobrane z kursora w celu usunięcia. – Guru

Odpowiedz

2

Jeśli użytkownik nie ma trudności z ponownym zastosowaniem uprawnień, prawdopodobnie łatwiej jest po prostu upuścić użytkownika i odtworzyć go.

+0

Upuszczenie użytkownika nie jest teraz możliwe. – NMan

1

To, co masz, to dobry początek.

Oto reszta:

  • mieć kursora i select. Potrzebujesz tylko kursora.
  • Następnym krokiem jest wywołanie instrukcji drop przy użyciu dynamicznego PLSQL. Użyłbym instrukcji EXECUTE IMMEDIATE. Jest bardziej elegancka i łatwiejsza w obsłudze, aby wybrać nazwę upuszczanej rzeczy i przesłać ją jako zmienną wiązania do WYKONAJ NATYCHMIAST.
  • Aby upuścić obiekty schematu wywołującego metodę, a nie schemat będący właścicielem metody, należy użyć "AUTORZY CURRENT_USER". Aby uzyskać więcej informacji, patrz the Oracle documentation.
  • Inne rzeczy do drop: pakunki, funkcji, procedur (system będzie prawdopodobnie powiesić następnie Timeout Jeśli spróbujesz upuścić tę metodę podczas gdy jego biegania), klasy Java, wyzwalacze, widoki, typy

Wreszcie, jest oczywiście bardzo niebezpieczną metodą, dlatego warto rozważyć umieszczenie jej w skrypcie zamiast w procedurze przechowywanej, aby nie było w bazie danych, aby ktokolwiek mógł go uruchomić.

1

Jesteś blisko - jak ktoś zauważył, potrzebujesz "WYKONAĆ NATYCHMIAST" dla wyciągu. należy wziąć pod uwagę:

  • Zamiast tworzyć procedury, aby to zrobić, uruchom to jako anonimowy bloku PL/SQL, więc nie ma problemu próbuje zrzucić procedurę, która jest uruchomiona.

  • Dodaj test dla typu obiektu TABELI iw tym przypadku zmodyfikuj instrukcję drop, aby dołączyć opcję kaskady do obsługi tabel, które są "rodzicami" innych tabel za pomocą ograniczeń klucza obcego. Pamiętaj, że prawdopodobnie będziesz generował listę kursorów w kolejności, która nie uwzględnia zależności, które zablokują spadek.

  • Również na temat zależności najlepiej jest najpierw upuścić tabele (dodać DECODE do kursora, który przypisuje niższą wartość liczbową do tego typu obiektu i nakazać wybór kursora tą wartością). Jeśli obiekty Oracle typu TYPE, które są używane jako typy kolumn w definicji tabeli, należy najpierw usunąć tabelę.

  • W przypadku korzystania z Oracle Advanced Queuing obiekty związane z tym MUSZĄ zostać usunięte za pomocą wywołań API pakietu AQ. Chociaż można usunąć tabele generowane przez Oracle w celu obsługi kolejek za pomocą zwykłej tabeli DROP, znajdziecie się w pozycji catch-22, a następnie nie będziecie mogli usuwać powiązanych kolejek ani dodawać ich ponownie.Do wersji 10g przynajmniej nie mogła nawet spaść schemat zawierający pominięciem bazy danych w trybie specjalnym, gdy taka sytuacja istniał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

Działa to dla mnie – Ewerton

+0

raport rror: ORA-00933: polecenie SQL nie prawidłowo zakończony ORA-06512: w linii 8 00933. 00000 - "polecenie SQL nie prawidłowo zakończony" – Suyash

+0

Tylko jedna uwaga: Aby pracować z Typ "JAVA SOURCE", należy dwukrotnie podać nazwę obiektu, ponieważ mogą zawierać znaki specjalne, które wymagają cytowania (np./2bbec77c_JsonEncoding). Oprócz tej małej (ale niezbędnej) modyfikacji, działa świetnie. Dzięki! – 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; 

Tworzenie powyższą funkcję (autonomiczny może być tak DDL nazywany przez funkcję) następnie można po prostu:

select DROP_ALL_SCHEMA_OBJECTS from dual; 

gdy chcesz usunąć wszystkie przedmioty, upewnij się, że nie starają się upuścić proc swój bieg (I dont care o proc s to dlaczego nie mam procs lub funkcje na liście TYP_OBIEKTU)

jeśli chcesz rzucić wszystko, czego potrzeba anonimowego Blokuj

ale muszę być w stanie to zrobić z poziomu narzędzia, które tylko pozwoliły ANSI SQL (nie plsql) stąd przechowywany proc.

Ciesz się.

+0

Działa dobrze - ładnie wykonane. –

+0

Przyszłam, aby dowiedzieć się, jak usunąć ** jedną ** funkcję. Po prostu powtórzę to, czego się dowiedziałem, ponieważ nikt nie mówi, jak działa skasowanie. 'wykonaj natychmiast (ciąg)' np. 'wykonaj natychmiast ('drop function myStupidFunction')' ~ sprawdź spacje. – Bitterblue

2

Dzięki Martin Brambley,

czuję możemy uprościć odpowiedzi w następujący sposób.

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

Dzięki Martin Brambley i Vijayan Srinivasan!

wersja

ale Vijayan Srinivasan nie jest prawidłowe, ponieważ obiekty zależne od typu „typu” kiedyś generuje błędy podczas upuść:

ORA-02303: nie może spaść lub wymienić typ z typu lub stołowych utrzymaniu

Moja wersja upuść wszystkich obiektów od schematu z dodatkowym:

  • procedury i funkcje (drop oczekiwać 'DROP_ALL_SCHEMA_OBJECTS')
  • kropla wszystkie zadania i dbms_jobs
  • upuść wszystkie db_links
  • nie upuścić tabele zagnieżdżone, ponieważ Droping tabel zagnieżdżonych nieobsługiwane
 
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; 

Powiązane problemy