2013-09-05 9 views
10

Mam problem, kiedy próbuję skompilować mój projekt w bazie danych Oracle. Aby było prostsze, mam trzy obiekty: 2 pakiety (UTILS i TYPY) i 1 widok (VIEW).Pętla zależności obiektu Oracle

Pakiet UTILS używa typów zdefiniowanych w TYPACH paczki. Pakiet TYPES używa VIEW jako podstawy dla jednego z typów. A VIEW używa funkcji z pakietu UTILS w swoim skrypcie. Kiedy próbuję wprowadzić zmiany w jednym z tych obiektów, nie mogę skompilować, ponieważ wszystko jest w nieprawidłowym stanie. Powstaje więc pewna pętla zależności obiektów.

Proszę, pomóż mi rozwiązać ten problem.

Na przykład, czy mimo to istnieje potrzeba skompilowania poniższego kodu? Każdy obiekt jest indywidualnie poprawny pod względem składni, ale jak można je wszystkie zestawiać razem?

create or replace package my_types is 
    type type1 is table of number; 
    type type2 is table of my_view%rowtype; 
end; 
/

create or replace package my_utils is 
    function get_1 return number; 
    procedure do_something(parameter my_types.type2); 
end; 
/

create or replace package body my_utils is 
    function get_1 return number is 
    begin 
     return 1; 
    end; 

    procedure do_something(parameter my_types.type2) is 
    begin 
     null; 
    end; 
end; 
/

create or replace force view my_view as 
select * from dual 
where 1 = my_utils.get_1(); 

exec dbms_utility.compile_schema(user, false); 

select object_name from user_objects where status <> 'VALID'; 
+0

Przerwać cykl? Spraw, aby wykonywanie funkcji było uruchomione (zamiast pieczenia w zapytaniu) - np: WYKONUJ funkcję z ciągu znaków. –

+0

Zerwanie pętli jest jedynym wyjściem z tego problemu? Pomyślałem, że podczas kompilowania pakietu/widoku może istnieć jakiś król wskazówka, aby zignorować nieprawidłowy stan jego zależności. – artbro

+0

Nie mam pojęcia - będziesz chciał, aby jakiś oracle wiedział wszystko :-) Bardziej zaznajomię się z Postgres i tak bym to zrobił. (nie cierpi z tego * dokładnego * problemu, ale nadal możesz tworzyć pętle zależności). –

Odpowiedz

1

Jeśli nie chcesz/nie możesz podzielić paczki ani widoku, zawsze możesz najpierw utworzyć atrapową wersję swojego widoku, skompilować pakiety i później stworzyć "prawdziwy" widok:

create or replace package my_types is 
    type type1 is table of number; 
    type type2 is table of my_view%rowtype; 
end; 
/

create or replace package my_utils is 
    function get_1 return number; 
    procedure do_something(parameter my_types.type2); 
end; 
/

create or replace package body my_utils is 
    function get_1 return number is 
    begin 
     return 1; 
    end; 

    procedure do_something(parameter my_types.type2) is 
    begin 
     null; 
    end; 
end; 
/

create or replace force view my_view as 
select * from dual; 

exec dbms_utility.compile_schema(user, false); 

create or replace force view my_view as 
select * from dual 
where 1 = my_utils.get_1(); 

select object_name from user_objects where status <> 'VALID'; 
+0

To nie działa w 11.2.0.3.0. Sztuczka sztucznej wersji działa dla prostych zależności dwukierunkowych, ale nie działa w tej sytuacji. –

+1

@jonearles Testowałem go na 11.1.0.6, gdzie działa dobrze. Jeśli przetestujesz go w wersji 11.2.0.3 - czy wszystkie obiekty są nieaktualne po rekompilacji? –

+1

Tak, wszystkie są nieprawidłowe. Nie działa także w Express Edition, 11.2.0.2, tutaj jest [SQL Fiddle] (http://sqlfiddle.com/#!4/44f94/1). Być może jest to błąd w wersji 11.2, ale nie mogłem znaleźć niczego w pomocy technicznej Oracle. –

3

Jeśli złamiesz widok w dwóch widokach, można złamać cykliczną zależność:

create or replace view my_view_1 
as select * from dual; 

create or replace package my_types is 
    type type1 is table of number; 
    type type2 is table of my_view_1%rowtype; 
end; 
/

create or replace package my_utils is 
    function get_1 return number; 
    procedure do_something(parameter my_types.type2); 
end; 
/

create or replace package body my_utils is 
    function get_1 return number is 
    begin 
     return 1; 
    end; 

    procedure do_something(parameter my_types.type2) is 
    begin 
     null; 
    end; 
end; 
/

create or replace view my_view as 
select * from my_view_1 
where 1 = my_utils.get_1(); 

EDIT: Inną możliwością jest przełamanie my_utils pakiet na dwie części:

create or replace package my_utils_1 is 
    function get_1 return number; 
end; 
/
create or replace package body my_utils_1 is 
    function get_1 return number is 
    begin 
     return 1; 
    end; 
end; 
/

create or replace view my_view as 
select * from dual 
where 1 = my_utils_1.get_1(); 

create or replace package my_types is 
    type type1 is table of number; 
    type type2 is table of my_view%rowtype; 
end; 
/

create or replace package my_utils_2 is 
    procedure do_something(parameter my_types.type2); 
end; 
/
create or replace package body my_utils_2 is 
    procedure do_something(parameter my_types.type2) is 
    begin 
     null; 
    end; 
end; 
/
+0

+1 To możliwe rozwiązanie, ale dla nagrody szukam czegoś trochę lepszego. Tworzenie dwóch widoków nie jest idealne, ponieważ trzeba je synchronizować. A w bardziej realistycznym scenariuszu pogląd nie mógł być tak łatwo podzielony bez powielania dużej logiki. –

2

Nie używałbym typów paczkowych i% ROWTYPE. Nie są to standardowe SQL i mogą być zastąpione przez Structured Types

create or replace view my_view_1 
as select * from dual; 

create or replace type type1 as table of number; 
create or replace type type2 as object (DUMMY VARCHAR2(1 byte)); 
create or replace type table_type2 as table of type2; 

create or replace package my_utils is 
    function get_1 return number; 
    procedure do_something(parameter table_type2); 
end; 
/

create or replace package body my_utils is 
    function get_1 return number is 
    begin 
     return 1; 
    end; 

    procedure do_something(parameter table_type2) is 
    begin 
     null; 
    end; 
end; 
/

create or replace view my_view as 
select * from my_view_1 
where 1 = my_utils.get_1(); 
+0

Nie jestem pewien, jaki standardowy SQL wprowadza do tabeli tutaj. W zależności od użycia typu obiektu (którego tutaj nie widzimy), może karzeć wydajność ... – igr

+0

Typy pakietów i% ROWTYPE mogą być używane tylko w PL/SQL. Nie można ich wybrać za pomocą zapytań SQL lub widoków. Pod względem wydajności nie będą się różnić –

Powiązane problemy