2013-06-16 32 views
7

Czy istnieje funkcja PL/SQL wyświetlająca dokładny typ zmiennej, np. Funkcja DUMP w SQL?Jak wyświetlić typ zmiennej w PL/SQL?

Próbowałem następujące

DECLARE 
    l_variable INTEGER := 1; 
BEGIN 
    DBMS_OUTPUT.PUT_LINE (DUMP (l_variable)); 
END; 

Ale daje następujący błąd:

PLS-00204: function or pseudo-column 'DUMP' may be used inside a SQL statement only

+1

Dlaczego chcesz to zrobić? DUMP() jest narzędziem diagnostycznym, używanym głównie do badania * zawartości * kolumn tabeli. Dlaczego należy sprawdzać typy danych zmiennych PL/SQL? (Mam kilka hipotez, ale myślę, że pytanie poprawiłoby więcej szczegółów dotyczących przypadku użycia.) – APC

+0

Początkowo chciałem tylko znaleźć dokładny typ zmiennej pętli autodeklarowanej w numerycznej FOR LOOP. Następnie zacząłem się zastanawiać, w jaki sposób można programowo uzyskać rzeczywisty typ dowolnej zmiennej, jak w każdym nowoczesnym języku, takim jak C#, java lub python, i nie znalazłem żadnego sposobu. – csadam

Odpowiedz

5

Możesz utworzyć tę funkcję przy użyciu PL/Scope. Ale nie zadziała z anonimowymi blokami i będziesz musiał odwoływać się do zmiennej jako łańcucha znaków.

create or replace function get_plsql_type_name 
(
    p_object_name varchar2, 
    p_name varchar2 
) return varchar2 is 
    v_type_name varchar2(4000); 
begin 
    select reference.name into v_type_name 
    from user_identifiers declaration 
    join user_identifiers reference 
     on declaration.usage_id = reference.usage_context_id 
     and declaration.object_name = reference.object_name 
    where 
     declaration.object_name = p_object_name 
     and declaration.usage = 'DECLARATION' 
     and reference.usage = 'REFERENCE' 
     and declaration.name = p_name; 

    return v_type_name; 
end; 
/

Przykład:

alter session set plscope_settings = 'IDENTIFIERS:ALL'; 

create or replace type my_weird_type is object 
(
    a number 
); 

create or replace procedure test_procedure is 
    var1 number; 
    var2 integer; 
    var3 my_weird_type; 
    subtype my_subtype is pls_integer range 42 .. 43; 
    var4 my_subtype; 
begin 
    dbms_output.put_line(get_plsql_type_name('TEST_PROCEDURE', 'VAR1')); 
    dbms_output.put_line(get_plsql_type_name('TEST_PROCEDURE', 'VAR2')); 
    dbms_output.put_line(get_plsql_type_name('TEST_PROCEDURE', 'VAR3')); 
    dbms_output.put_line(get_plsql_type_name('TEST_PROCEDURE', 'VAR4')); 
end; 
/

begin 
    test_procedure; 
end; 
/

NUMBER 
INTEGER 
MY_WEIRD_TYPE 
MY_SUBTYPE 
+0

Po prostu zdałem sobie sprawę, że może to powodować pewne problemy w zależności od sposobu użycia. Jeśli zmienna nie istnieje, otrzymasz 'NO_DATA_FOUND', a jeśli w obiekcie znajdują się dwie zmienne o tej samej nazwie, to otrzymasz' ORA-01422: dokładne pobieranie zwraca więcej niż żądana liczba wierszy'. –

+0

Nie ma problemu, mam pomysł. Używałem tylko starszych wersji niż 11g, więc nie wiedziałem o tej funkcji. Wygląda na to, że muszę zaktualizować swoją wiedzę, ponieważ 12c też jest dostępne :) – csadam

1
declare 
    a number(10,3); 
    type_info varchar2(400); 
begin 
    a := 55.5; 
    select dump(a) into type_info from dual; 
    DBMS_OUTPUT.PUT_LINE(type_info); 
end; 
+2

Myślałem o tym rozwiązaniu, ale w tym przypadku następuje niejawna konwersja. Na przykład, jeśli przekażę PLS_INTEGER, staje się typ = 2 NUMBER. – csadam

+0

@csadam: I to jest poprawne. PLS_INTEGER jest podtypem BINARY_INTEGER, który jest podtypem INTEGER, który jest aliasem dla NUMBER. Domyślam się, że zwraca poprawną wartość. –

+0

@csadam: Jeśli uważasz, że nazwiesz proc/func na podstawie odkrycia typu, to idziesz w złym kierunku. Jest na to sposób, ale nie jest to zalecane. –

2

jak należy zauważyć, NORA jest przeciążony funkcji. ma 3 przeciążenia.

Możesz symulować to samo w swoim kodzie.

function myDump (x Varchar2) return varchar2 is begin return('string') ; end ; 
function myDump (x number) return varchar2 is begin return('integer') ; end ; 
function myDump (x date) return varchar2 is begin return('date') ; end ; 

Powyższy kod może nie działać poprawnie, ale powinien dać Ci pomysł rozwiązania problemu.

Mam nadzieję, że spełni to Twoje wymagania.

Uwaga; możesz umieścić te funkcje w Pakiecie i użyć ich odpowiednio.

+0

To rozwiązanie nie będzie w stanie odróżnić 'NUMBER' od' INTEGER'. Jeśli utworzysz funkcję dla każdego typu w pakiecie, to zostanie ona skompilowana, ale gdy ją wywołasz, otrzymasz komunikat o błędzie 'PLS-00307: zbyt wiele deklaracji 'MYDUMP' pasuje do tego połączenia'. Naprawdę trudną częścią tego pytania jest rozróżnienie między podtypami, ponieważ PL/SQL wydaje się nie znać różnicy w każdym kontekście. –

+0

Cześć Ali, kreatywne podejście. To nie jest idealne, jak zauważyli @jonearles, ale wciąż lepsze niż inne w wersjach DB poniżej 11g. Mogłabym to przyjąć za odpowiedź poniżej 11g. Ale nie ograniczyłem wersji DB w pytaniu, a rozwiązanie 11g jest lepsze, więc muszę dać nagrodę jonearles – csadam

+0

Te funkcje będą działać tylko dla natywnych typów oracle. Wyrocznia Rodzime typy nie powodują żadnej różnicy między liczbą a liczbą całkowitą. @jonearles dał dobre wyjaśnienie, powodem, dla którego dałem ci inną alternatywę jest to, że możesz mieć prostszą prośbę. –