查找块中游标或表列的数据类型

时间:2012-01-09 14:44:51

标签: oracle plsql oracle11g oracle9i oracle11gr2

是否可以使用系统表找出块中没有的游标或变量列的数据类型?虽然我知道我可以使用系统表来查找这些信息,但速度会慢得多。

类似的东西,

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,我无法找到任何办法,这对我的最终目的来说太过分了。

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

而且,是的,我知道甲骨文版本的数量是荒谬的,但这是我们目前所获得的数量... 9i很快就会死于支持11但如果我可以立即运行9i代码找到答案!但我包括11,因为我可以等待更好的解决方案,如果需要,

2 个答案:

答案 0 :(得分:4)

使用dump功能,并将结果与​​this代码进行比较。

  

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

答案 1 :(得分:3)

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

对于大多数情况似乎没必要,因为在大多数情况下我们已经知道类型(强类型)。例如,过程参数通常会指定类型(数字,varchar2,等等)。局部变量通常会通过%type notation指定类型或将自身绑定到数据库对象类型。

在某些情况下,弱类型对象是需要或有用的,例如可用于任何查询的弱类型游标变量。一个过于简单的例子:

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"

希望不会太长时间的回应;)