PL/SQL中如何查看变量的类型?
Posted
技术标签:
【中文标题】PL/SQL中如何查看变量的类型?【英文标题】:How to view the type of a variable in PL/SQL? 【发布时间】:2013-06-16 14:25:30 【问题描述】:PL/SQL 中是否有显示变量确切类型的函数,如 SQL 中的 DUMP 函数?
我已经尝试了以下
DECLARE
l_variable INTEGER := 1;
BEGIN
DBMS_OUTPUT.PUT_LINE (DUMP (l_variable));
END;
但它给出了以下错误:
PLS-00204:函数或伪列“DUMP”可能在 SQL 中使用 仅声明
【问题讨论】:
为什么要这样做? DUMP() 是一个诊断工具,主要用于调查表列的内容。为什么需要询问 PL/SQL 变量的数据类型? (我有几个假设,但我认为通过有关用例的更多细节可以改进这个问题。) 最初我只是想在数字 FOR LOOP 中找出自动声明的循环变量的确切类型。然后我开始想知道如何以编程方式获取任何变量的实际类型,例如 C#、java 或 python 等任何现代语言,但我没有找到任何方法。 【参考方案1】:您可以使用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
【讨论】:
我刚刚意识到这可能会遇到一些问题,具体取决于它的使用方式。如果变量不存在,您将获得NO_DATA_FOUND
,如果对象中有两个同名变量,您将获得ORA-01422: exact fetch returns more than requested number of rows
。
没问题,我知道了。我只使用了 11g 以上的旧版本,所以我不知道这个功能。看来我必须更新我的知识,因为 12c 也出来了:)【参考方案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 ;
上面的代码可能无法正常工作,但应该让你知道如何处理这个问题。
我希望这能满足您的要求。
注意;您可以将这些功能放在一个包中并相应地使用它们。
【讨论】:
此解决方案将无法区分NUMBER
和 INTEGER
。如果您为包中的每种类型创建一个函数,它将编译,但是当您调用它时,您将收到错误消息PLS-00307: too many declarations of 'MYDUMP' match this call
。这个问题真正棘手的部分是区分子类型,因为 PL/SQL 似乎并不知道每种情况下的区别。
嗨,阿里,创意方法。正如@jonearles 指出的那样,它并不完美,但在 11g 以下的 DB 版本中仍然比其他版本更好。对于 11g 以下的答案,我可以接受。但是问题里我没有限制DB版本,11g的方案更好,所以只好给jonearles赏金了
这些函数仅适用于 oracle 原生类型。并且 oracle Native 类型在 Number 和 Integer 之间没有任何区别。 @jonearles 给出了很好的解释,我给你另一个选择的原因是你可能有一个更简单的请求。【参考方案3】:
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;
【讨论】:
我已经考虑过这个解决方案,但是在这种情况下会发生隐式转换。例如,如果我传入一个 PLS_INTEGER,它就会变成 typ=2 NUMBER。 @csadam:这是正确的。 PLS_INTEGER 是 BINARY_INTEGER 的子类型,它是 INTEGER 的子类型,INTEGER 是 NUMBER 的别名。所以我猜它会返回正确的值。 @csadam:如果你认为你会根据类型发现调用一些 proc/func,那么你就走错了方向。有办法,但不推荐。 @the_slk 我的目的只是深入挖掘,看看幕后到底发生了什么。例如,在 .NET 中,我可以挖掘“虚拟”字节码,查看真正执行的内容,并查看优化器在我的源代码中发生了什么变化。没什么大不了的,只是好奇。以上是关于PL/SQL中如何查看变量的类型?的主要内容,如果未能解决你的问题,请参考以下文章
PL/SQL 如何查看当前连接信息以及SQL PLUS如何指定IP地址