Oracle 如何在PL/SQL中查看变量的类型?

Oracle 如何在PL/SQL中查看变量的类型?,oracle,variables,reflection,plsql,dump,Oracle,Variables,Reflection,Plsql,Dump,PL/SQL中是否有一个函数可以显示变量的确切类型,比如SQL中的DUMP函数 我试过以下方法 DECLARE l_variable INTEGER := 1; BEGIN DBMS_OUTPUT.PUT_LINE (DUMP (l_variable)); END; 但它给出了以下错误: PLS-00204:函数或伪列“DUMP”可在SQL中使用 仅声明 您可以使用创建此函数。但是它不适用于匿名块,您需要将变量作为字符串引用 create or replace function

PL/SQL中是否有一个函数可以显示变量的确切类型,比如SQL中的DUMP函数

我试过以下方法

DECLARE
   l_variable   INTEGER := 1;
BEGIN
   DBMS_OUTPUT.PUT_LINE (DUMP (l_variable));
END;
但它给出了以下错误:

PLS-00204:函数或伪列“DUMP”可在SQL中使用 仅声明


您可以使用创建此函数。但是它不适用于匿名块,您需要将变量作为字符串引用

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

您应该注意到,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 ;
上面的代码可能无法正常工作,但应该会告诉您如何处理该问题

我希望这能满足你的要求


注;您可以将这些函数放在一个包中,并相应地使用它们

我考虑过这个解决方案,但在这种情况下会发生隐式转换。例如,如果我传入一个PLS_整数,它将变成一个典型的=2的数字。@csadam:这是正确的。PLS_INTEGER是二进制_INTEGER的子类型,二进制_INTEGER是整数的子类型,整数是数字的别名。所以我猜它返回的值是正确的。@csadam:如果您认为您将基于类型发现调用某些proc/func,那么您就走错了方向。有办法,但不推荐。@slk我的目的只是想挖引擎盖下面,看看里面到底发生了什么,幕后。例如,在.NET中,我可以挖掘“虚拟”字节码,查看真正执行的是什么,并查看优化器在我的源代码中更改了什么。不过没什么大不了的,只是好奇而已。我刚刚意识到这可能会遇到一些问题,这取决于它的使用方式。如果变量不存在,您将得到一个
找不到数据
,如果对象中有两个同名的变量,您将得到
ORA-01422:exact fetch返回的行数大于请求的行数
。没问题,我知道了。我只使用了比11g更旧的版本,所以我不知道这个功能。看起来我必须更新我的知识,因为12c也已失效:)此解决方案将无法区分
数字
整数
。如果您为包中的每种类型创建一个函数,它将被编译,但是当您调用它时,您将收到错误消息
PLS-00307:MYDUMP的声明太多,与此调用匹配
。这个问题真正棘手的部分是区分不同的子类型,因为PL/SQL似乎并不知道每个上下文中的区别。它并不像@jonearles指出的那样完美,但在11g以下的DB版本中仍然比其他版本好。我可以在11克以下接受这个答案。但是我没有在这个问题上限制DB版本,11g解决方案更好,所以我必须赏赐JonerEst这些函数只适用于oracle本机类型。而oracle本机类型对数字和整数没有任何区别@jonearles给了一个很好的解释,我给你另一个选择的原因是你可能有一个更简单的请求。你为什么要这样做?DUMP()是一个诊断工具,主要用于调查表列的内容。为什么需要查询PL/SQL变量的数据类型?(我有两个假设,但我认为这个问题会因为更多关于用例的细节而得到改进。)最初我只是想找出数字FOR循环中自动声明的循环变量的确切类型。然后我开始思考如何通过编程获得任何变量的实际类型,就像在任何现代语言(如C#、java或python)中一样,我还没有找到任何方法。
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 ;