听起来好像您想要一个自我描述的对象。这意味着以编程方式查找变量的类型,而无需从某些元数据视图中进行选择。只要问对象,你是什么?
在大多数情况下似乎没有必要,因为在大多数情况下,我们已经知道类型(强类型)。例如,一个程序的参数通常会指定类型(number、varchar2 等)。局部变量通常会指定类型或通过 %type 表示法将自己绑定到数据库对象类型。
在某些情况下需要或使用弱类型对象,例如可用于任何查询的弱类型游标变量。一个过于简单的例子:
create or replace procedure get_data(o_cur OUT SYS_REFCURSOR) as
begin
OPEN o_cur FOR
-- without changing parameter, this could select from any table
select * from emp;
end;
现在的问题是,如果有人将游标编码为与另一个表一起使用(我故意选择了一个糟糕的过程名称),您可能会遇到错误(在运行时)。就像是:
declare
l_cur sys_refcursor;
l_row dept%rowtype;
begin
get_data(l_cur);
-- oops, I thought this was dept data when I coded it, Oracle didn't complain at compile time
LOOP
fetch l_cur
into l_row;
exit when l_cur%notfound;
-- do something here
END LOOP;
close l_cur;
end;
这也是为什么我更喜欢强类型游标并避免这种情况的原因。
无论如何,对于自描述对象,您可以使用 SYS.ANYDATA 内置类型(类似地,SYS.ANYDATASET 用于通用集合类型)。我相信这是在 9i 中引入的。例如,此过程根据类型获取一些数据和分支逻辑:
CREATE OR REPLACE procedure doStuffBasedOnType(i_data in sys.anydata) is
l_type SYS.ANYTYPE;
l_typecode PLS_INTEGER;
begin
-- test type
l_typecode := i_data.GetType (l_type);
CASE l_typecode
when Dbms_Types.Typecode_NUMBER then
-- do something with number
dbms_output.put_line('You gave me a number');
when Dbms_Types.TYPECODE_DATE then
-- do something with date
dbms_output.put_line('You gave me a date');
when Dbms_Types.TYPECODE_VARCHAR2 then
-- do something with varchar2
dbms_output.put_line('You gave me a varchar2');
else
-- didn't code for this type...
dbms_output.put_line('wtf?');
end case;
end;
在这里,您可以根据类型进行编程分支。并使用它:
declare
l_data sys.anydata;
begin
l_data := sys.anydata.convertvarchar2('Heres a string');
doStuffBasedOnType(l_data);
end;
-- output: "You gave me a varchar2"
希望这不是太冗长的回应;)