4

是否可以在不使用系统表的情况下找出块内游标或变量列的数据类型?虽然我知道我可以使用系统表来查找这些信息,但速度会慢很多。

就像是,

declare
   my_column_data_type varchar2(30);
begin
  my_column_data_type := all_tables.table_name%type;
  dbms_output.put_line(my_column_data_type);
end;

如果不诉诸 ,我找不到任何方法dbms_sql,这对于我的最终目的来说太过分了。

但是,甲骨文已经掌握了所有信息。如果我尝试将 a 分配varchar2给 anumber那么它会立即抱怨,因此它知道数据类型是什么。

而且,是的,我知道 Oracle 的版本数量很荒谬,但这就是我们目前所拥有的数量...... 9i 很快就会有利于 11,但如果我能找到答案,这段代码将立即在 9i 上运行!但我包括了 11 个,因为如果需要,我可以等待更好的解决方案,

4

2 回答 2

4

使用转储函数并将结果与​​此代码进行比较。

DUMP 返回一个 VARCHAR2 值,其中包含数据类型代码、字节长度和 expr 的内部表示。

于 2012-01-09T14:58:11.323 回答
3

听起来好像您想要一个自我描述的对象。这意味着以编程方式查找变量的类型,而无需从某些元数据视图中进行选择。只要问对象,你是什么?

在大多数情况下似乎没有必要,因为在大多数情况下,我们已经知道类型(强类型)。例如,一个程序的参数通常会指定类型(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"

希望这不是太冗长的回应;)

于 2012-01-10T12:46:14.633 回答