2013-06-16 16 views
7

SQLのDUMP関数のように、変数の正確な型を表示する関数がPL/SQLにありますか?PL/SQLで変数のタイプを表示する方法は?

私は、次の

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

を試みた。しかし、それは次のエラーを与える:

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

+1

なぜこれをやりたいですか? DUMP()は診断ツールで、主にテーブルの列の内容*を調べるために使用されます。 PL/SQL変数のデータ型を問い合せる必要があるのはなぜですか? (私はいくつかの仮説を持っていますが、ユースケースの詳細については質問が改善されると思っています) – APC

+0

最初に、数値ループの自動宣言ループ変数の正確なタイプを探したかっただけです。それから、私はC#、java、pythonのような現代的な言語のような、どのような変数の実際の型をプログラム的に得ることができるのだろうと思い始めました。 – csadam

答えて

5

あなたはPL/Scopeを使用してこの関数を作成することができます。しかし、無名ブロックでは動作しません。その変数を文字列として参照する必要があります。

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

例:

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

私は、これがどのように使用されているかによっていくつかの問題に遭遇するかもしれないことに気付きました。変数が存在しない場合は 'NO_DATA_FOUND'を取得し、オブジェクトに同じ名前の変数が2つある場合は、' ORA-01422:exact fetchは要求された行数よりも多くを返します '。 –

+0

問題はない、私は考えを持っている。私は11gより古いバージョンしか使用しなかったので、この機能についてはわかりませんでした。 12cも出ているので私の知識を更新する必要があるように見えます:) – 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

私はこの解決策について考えましたが、この場合暗黙の変換が行われます。たとえば、PLS_INTEGERを渡すと、typ = 2 NUMBERになります。 – csadam

+0

@csadam:それは正しいです。 PLS_INTEGERは、NUMBERの別名であるINTEGERのサブタイプであるBINARY_INTEGERのサブタイプです。だから私はそれが正しい値を返すと思います。 –

+0

@csadam:タイプディスカバリに基づいてproc/funcを呼び出すと間違った方向に向かいます。方法はありますが、推奨されません。 –

2

あなたは気付くはずとして、DUMPはオーバーロードされた関数です。 3つの過負荷があります。

コード内で同じことをシミュレートすることができます。

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 ; 

上記のコードは正しく動作しない可能性がありますが、問題の対処方法を教えてください。

これがあなたの要件を満たすことを願っています。

注:これらの関数をパッケージに入れて、それに応じて使用することができます。

+0

この解決策は 'NUMBER'と' INTEGER'を区別することができません。パッケージ内の各タイプの関数をコンパイルするとコンパイルされますが、コンパイルするとエラーメッセージ 'PLS-00307: 'MYDUMP'の宣言が多すぎます。 PL/SQLはすべてのコンテキストの違いを認識していないように見えるので、この質問の本当に面倒な部分はサブタイプを区別することです。 –

+0

こんにちはアリ、創造的なアプローチ。 @jonearlesが指摘したように完璧ではありませんが、11g未満のDBバージョンでは他のものより優れています。私は11gの下の答えでこれを受け入れることができました。しかし、私は質問のDBのバージョンを制約していないし、11gのソリューションが良いですので、私はjonearlesに賞金を与える必要があります – csadam

+0

これらの関数は、オラクルのネイティブタイプでのみ動作します。 and oracleネイティブ・タイプでは、NumberとIntegerの間に違いはありません。 @jonearlesは良い説明をしました。私があなたに他の選択肢を与えた理由は、よりシンプルなリクエストがあるかもしれないということです。 –

関連する問題