2017-10-31 10 views
4

このリンクは、プロシージャ/関数変数の型をOracleで取得する方法を示しています(View Type of a variable)。PL/SQLで変数のタイプを動的に表示するにはどうすればいいですか?

それはとてもスルー機能「get_plsql_type_name」を行います。上記の方法で問題は、それが静的であり、私は1つのサブタイプであることができ、変数のタイプを確認する必要があるということです

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

を手続き/関数のスコープで宣言されています。

上記の方法を使用すると、次のようになります。

Create the type and its subtype: 

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

CREATE OR REPLACE TYPE my_weird_subtype UNDER my_weird_type( 
    b number 
); 
/

テーブルを作成し、それを移入:

create table test_my_weird_type(
x my_weird_type, 
y my_weird_subtype 
); 

INSERT INTO test_my_weird_type (x,y) VALUES (my_weird_type(100),my_weird_subtype(100,200)); 
COMMIT; 

関数の作成(それが2つのmy_weird_typeパラメータがあり、時々私はそのサブタイプを使用する必要がつもりです):

create or replace function test_procedure (
    inn_type my_weird_type, 
    out_subtype my_weird_type 
) RETURN number is 
    var1 number; 
    var2 integer; 
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', 'INN_TYPE')); 
    dbms_output.put_line(get_plsql_type_name('TEST_PROCEDURE', 'OUT_SUBTYPE')); 

    return 1; 
end; 
/

ベロウクエリ:

select test_procedure(x,y) from test_my_weird_type; 

は、以下の出力を与える:

NUMBER 
INTEGER 
MY_WEIRD_TYPE 
MY_WEIRD_TYPE 

しかし、右出力される。

NUMBER 
INTEGER 
MY_WEIRD_TYPE 
MY_WEIRD_SUBTYPE 

関数はWICHサブタイプを認識する必要が使用されるbeeingており、従って 関数「get_plsql_type_name」は改善する必要があります。それを行う方法はありますか?

ありがとうございます。

答えて

1

関数 "get_plsql_type_name"を改善する必要があるため、サブタイプが使用されていることを認識する必要があります。それを行う方法は ですか?

番号はありません。 USER_IDENTIFIERSは、現在のユーザーが所有する(パッケージ/プロシージャ/関数などの)格納されたオブジェクトの識別子に関する情報を表示します。

OracleTYPESUBTYPEを識別するためにSQL範囲の下に作成スタンドアロンオブジェクトの任意のデータ・ディクショナリを提供doesnot。最大でTYPEと指定できます。

たとえば、あなたのケースでは、TYPEは、SUBTYPEと思っています。

SELECT * 
    FROM all_objects 
WHERE object_name = 'MY_WEIRD_SUBTYPE' 

編集:私は考えることができる

もう一つの方法は、あなたが渡す任意のTypeためSUPERTYPEを持っているかどうかを確認することです。その場合は、typesubtypeであることを意味します。

あなたのようなクエリを使用することができます:あなたは、あなたの関数でこの機能を実装することができ

SELECT 1 
    FROM user_types 
WHERE type_name = 'MY_WEIRD_SUBTYPE' 
and supertype_name is not null; 

をチェックする場合は、その SUBTYPE

+0

Ok ...ユーザーが渡したオブジェクト型を取得できない場合は、その属性を操作するためにその属性をどのように知ることができますか? – Siqueira

+0

'ユーザが渡したオブジェクト型を取得できない場合、その属性をどのように知ってそれを操作することができますか? - それを操作することはできません。 – XING

2
あなたは、機能仕様に基づいてタイプをテストすることはできません

SQL Fiddle

:しかし、あなたは IS OF(type)演算子を使用してオブジェクトに渡されたの種類や SYS_TYPEID functionをテストすることができます

Oracleの11グラムR2スキーマのセットアップ

CREATE type my_weird_type IS OBJECT 
(
    a NUMBER 
) NOT FINAL 
/

CREATE TYPE my_weird_subtype UNDER my_weird_type 
(
    b NUMBER 
) 
/

CREATE FUNCTION getType(
    i_type my_weird_type 
) RETURN VARCHAR2 
IS 
BEGIN 
    IF i_type IS OF(my_weird_subtype) THEN 
    RETURN 'subtype'; 
    ELSIF i_type IS OF(my_weird_type) THEN 
    RETURN 'type'; 
    ELSE 
    RETURN 'other'; 
    END IF; 
END; 
/

CREATE FUNCTION getType2(
    i_type my_weird_type 
) RETURN VARCHAR2 
IS 
    o_type USER_TYPES.TYPE_NAME%TYPE; 
BEGIN 
    SELECT type_name 
    INTO o_type 
    FROM user_types 
    WHERE typeid = SYS_TYPEID(i_type); 

    RETURN o_type; 
EXCEPTION 
    WHEN NO_DATA_FOUND THEN 
    RETURN NULL; 
END; 
/

create table test_my_weird_type(
    value my_weird_type 
) 
/

INSERT INTO test_my_weird_type (value) 
SELECT my_weird_type(1)  FROM DUAL UNION ALL 
SELECT my_weird_subtype(2,3) FROM DUAL UNION ALL 
SELECT NULL     FROM DUAL 
/

クエリ1

SELECT t.value.a AS a, 
     TREAT(t.value AS my_weird_subtype).b AS b, 
     getType(value), 
     getType2(value) 
FROM test_my_weird_type t 

Results

|  A |  B | GETTYPE(VALUE) | GETTYPE2(VALUE) | 
|--------|--------|----------------|------------------| 
|  1 | (null) |   type | MY_WEIRD_TYPE | 
|  2 |  3 |  subtype | MY_WEIRD_SUBTYPE | 
| (null) | (null) |   other |   (null) | 
+0

これは一般的なものではなく、非常に疑問のある解決策です。私は、OPが何らかのタイプを作成した場合、そのたびに関数を変更する必要があり、それが意図ではないと思います。しかし、 'IS OF(type)'演算子を知っておいて良かったです。 – XING

+0

ok ...ユーザーが渡したオブジェクト型を取得できない場合は、その属性を操作するためにその属性をどのように知ることができますか? – Siqueira

+0

@XING 'SYS_TYPEID'関数を使うこともできます。 – MT0

1

ANYDATAANYTYPEは、Oracleオブジェクトに対する完全な動的制御を可能にします。このアプローチは、静的コード分析アプローチとは無関係です。

select 
    get_type_name(AnyData.ConvertObject(x)) x_type, 
    get_type_name(AnyData.ConvertObject(y)) y_type 
from test_my_weird_type; 

X_TYPE   Y_TYPE 
------   ------ 
MY_WEIRD_TYPE MY_WEIRD_SUBTYPE 

その関数はおそらくありません:オブジェクトはAnyData.ConvertObjectで変換しなければならない関数を呼び出す前に

create or replace function get_dynamic_type_name(
    p_anydata anydata 
) return varchar2 is 
    v_typecode pls_integer; 
    v_anytype anytype; 

    v_prec  pls_integer; 
    v_scale  pls_integer; 
    v_len   pls_integer; 
    v_csid  pls_integer; 
    v_csfrm  pls_integer; 
    v_schema_name varchar2(128); 
    v_type_name varchar2(128); 
    v_version  varchar2(32767); 
    v_numelems pls_integer; 
    v_result pls_integer; 
begin 
    v_typecode := p_anydata.getType(v_anytype); 

    v_result := v_anytype.GetInfo 
    (
     prec  => v_prec, 
     scale  => v_scale, 
     len   => v_len, 
     csid  => v_csid, 
     csfrm  => v_csfrm, 
     schema_name => v_schema_name, 
     type_name => v_type_name, 
     version  => v_version, 
     numelems => v_numelems 
    ); 

    return v_type_name; 
end get_dynamic_type_name; 
/

はたとえば、この機能は、任意のオブジェクトの入力のための実際の型名を返します。単純に型名を取得する最も便利な方法です。しかし、ANY型を使用してPL/SQLリフレクションを実装し、オブジェクトを事前に知らなくてもオブジェクトを操作する方法を示します。たとえば、私の答えは、他の回答hereに基づいています。これは、オブジェクトの最初の属性を見つける方法を示しています。

ANYタイプは面白いですが、控えめに使用する必要があります。通常、動的SQLですべての処理を行うのではなく、動的SQLを使用してデータを処理する静的コードを生成する方が、迅速かつ簡単です。私は可能な限りオブジェクトリレーショナルデータベース機能を避けようとしています。あなたのスキーマはスマートにしてください。

+0

ありがとう...私はあなたのソリューションをテストし、できるだけ早くフィードバックを与えるつもりです! – Siqueira

関連する問題