2013-06-16 8 views
7

Gibt es in PL/SQL eine Funktion, um den genauen Typ einer Variablen anzuzeigen, wie die DUMP-Funktion in SQL?Wie sieht man den Typ einer Variablen in PL/SQL?

Ich habe versucht, die folgende

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

Aber es gibt den folgenden Fehler:

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

+1

Warum möchten Sie das tun? DUMP() ist ein Diagnosetool, das hauptsächlich zur Untersuchung des * Inhalts * von Tabellenspalten verwendet wird. Warum müssen Sie die Datentypen von PL/SQL-Variablen abfragen? (Ich habe ein paar Hypothesen, aber ich denke, die Frage würde durch weitere Details bezüglich des Anwendungsfalls verbessert werden.) – APC

+0

Ursprünglich wollte ich nur den genauen Typ der autodeclarierten Schleifenvariablen in einem numerischen FOR LOOP herausfinden. Dann begann ich mich zu fragen, wie ich programmatisch den tatsächlichen Typ einer Variablen erhalten kann, wie in jeder modernen Sprache wie C#, Java oder Python, und ich habe keinen Weg gefunden. – csadam

Antwort

5

Sie diese Funktion PL/Scope mit erstellen können. Aber es funktioniert nicht mit anonymen Blöcken und Sie müssen die Variable als String referenzieren.

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; 
/

Beispiel:

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

Ich habe gerade festgestellt, dass dies je nachdem, wie es verwendet wird, zu einigen Problemen führen kann. Wenn die Variable nicht existiert, erhalten Sie ein 'NO_DATA_FOUND', und wenn es zwei Variablen mit dem gleichen Namen im Objekt gibt, erhalten Sie' ORA-01422: exact fetch liefert mehr als die angeforderte Anzahl an Zeilen'. –

+0

Kein Problem, ich habe die Idee. Ich habe nur ältere Versionen als 11g verwendet, also wusste ich nichts über diese Funktion. Sieht so aus, als ob ich mein Wissen aktualisieren muss, weil die 12c ebenfalls aus ist :) – 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

Ich habe über diese Lösung nachgedacht, aber in diesem Fall kommt es zu einer impliziten Konvertierung. Zum Beispiel, wenn ich einen PLS_INTEGER übergebe, wird es eine typ = 2 NUMMER. – csadam

+0

@csadam: Und das ist richtig. PLS_INTEGER ist ein Untertyp von BINARY_INTEGER, der ein Untertyp von INTEGER ist, der ein Alias ​​für NUMBER ist. Ich denke, es gibt den richtigen Wert zurück. –

+0

@csadam: Wenn Sie denken, dass Sie einige proc/func basierend auf Typentdeckung aufrufen werden, dann gehen Sie in die falsche Richtung. Es gibt einen Weg dafür aber nicht zu empfehlen. –

2

wie Sie feststellen sollten, DUMP ist eine überladene Funktion. es hat 3 Überladungen.

So können Sie das gleiche in Ihrem Code simulieren.

Der obige Code funktioniert möglicherweise nicht richtig, aber sollte Ihnen die Idee geben, wie Sie das Problem lösen.

Ich hoffe, dass dies Ihre Anforderungen erfüllen wird.

Hinweis; Sie können diese Funktionen in ein Paket einfügen und entsprechend verwenden.

+0

Diese Lösung wird nicht in der Lage sein, zwischen einer 'NUMBER' und einem' INTEGER' zu unterscheiden. Wenn Sie eine Funktion für jeden Typ in einem Paket erstellen, wird es kompiliert, aber wenn Sie es aufrufen, erhalten Sie die Fehlermeldung 'PLS-00307: zu viele Deklarationen von 'MYDUMP' stimmen mit diesem Aufruf überein. Der wirklich knifflige Teil dieser Frage ist die Unterscheidung zwischen Subtypen, da PL/SQL den Unterschied in jedem Kontext nicht zu kennen scheint. –

+0

Hi Ali, kreativer Ansatz. Es ist nicht perfekt, wie @jonearles darauf hingewiesen hat, aber immer noch besser als andere in DB-Versionen unter 11g. Ich könnte dies für die Antwort unter 11g akzeptieren. Aber ich habe die DB-Version in der Frage nicht eingeschränkt, und die 11g-Lösung ist besser, also muss ich das Kopfgeld jonearles geben – csadam

+0

Diese Funktionen funktionieren nur für native Oracle-Typen. Und Oracle Native-Typen machen keinen Unterschied zwischen Number und Integer. @ Jonearles gab eine gute Erklärung, Grund, warum ich Ihnen eine andere Alternative gab, ist, dass Sie eine einfachere Anfrage haben könnten. –