如何在plsql中动态定义类型

时间:2011-05-12 04:31:06

标签: sql oracle plsql

我有一个这样的程序:

create or replace procedure pname (tn varchar2) is
-- here i want to declare the variable

  col1 tn%COL_ID

begin

end;

我知道我作为参数传递的每个表都将包含名为COL_ID的列。但我无法做到这一点,我收到这样的错误

  

PLS-00487:对变量'tn'的无效引用        PL / SQL:项目被忽略         PLS-00487:对变量'tn'的无效引用         PL / SQL:项目被忽略

请帮我说明如何声明变量。

3 个答案:

答案 0 :(得分:4)

有趣的问题。正如APC所指出的那样,Oracle并没有像其他语言那样反思,所以传递名称(varchar2)对Oracle没有多大帮助(特别是在编译时)。我相信你在这里说的是你有一组表都具有某些特征(同一类型的1个或更多列以相同的方式使用),所以你想要制作一个适用于任何一个的通用函数它们。

您可以执行此操作,但您必须定义一个对象类型,以定义各个表共享的公共列和类型。说这是以下两列:

create or replace type my_obj as object (name varchar2(100), num number);

现在你的函数(或程序)将接受这种类型作为参数:

create or replace function my_fn(obj my_obj) return varchar2 is
  begin
    -- do something with object
    return obj.name || ',' || obj.num;
  end;

你会这样称呼:

declare
    obj my_obj;
    rv varchar2(1000);
  begin
    for rec in (select * from sometable)
    loop
      obj := my_obj(rec.some_varchar_col, rec.some_number_col);
      select my_fn(obj) into rv from dual;
      dbms_output.put_line(rv);
    end loop;
  end;

我能想到的唯一另一种方法是接受一个弱类型的sys_refcursor,然后强制调用procs发送一个正确的游标(由于潜在的运行时异常而且不是很清楚)。如果编写“通用”函数,我更喜欢上述方法。

EDIT 为了完成,我将引入上面提到的sys_refcursor示例:

create or replace procedure my_proc(cur sys_refcursor) is
  v_name varchar2(100);
  v_num number;
begin
  loop
    fetch cur into v_name, v_num;
    exit when cur%notfound;

    -- do something with our common fields
    dbms_output.put_line(v_name || ',' || v_num);
  end loop;
end;

并称之为:

declare
  v_cur sys_refcursor;
begin
  open v_cur for select my_name, my_num from some_table;
  my_proc(v_cur);
  close v_cur;
end;

请注意 这看起来过于简单,只有2列(为什么不将params设置为varchar2和number),但是你可能需要在函数中处理几十列,输入对象可以填充任意数量的列。

干杯

答案 1 :(得分:3)

语法是:

declare
    col1  t23.col1%type;
begin
    null;
end;
/ 

Oracle文档集在线。 Find it here。有关%TYPE的信息位于the PL/SQL User's Guide


  

“在你的例子中,t23是一个表。不是   带有表名的参数。“

公平点。我假设COL1的每个声明都是相同的数据类型,因此声明它使用一个固定的表名将适用于所有表。如果情况并非如此,那么我同意我的解决方案不起作用。

传递表名的问题通常是:PL / SQL不支持它。它没有像Java中的反射那样。

总是有动态SQL,但这可能有点过分。我认为OP需要提供有关他们想要实现的目标的更多细节。

答案 2 :(得分:3)

查看COL_ID在您可能传递给过程的所有表中使用的所有数据类型。它们都可能适合其中一种基本数据类型 - 即NUMBERVARCHAR2(4000)

为每种数据类型创建一个单独的过程,调用适当的过程版本(或者,在过程中确定要与逻辑一起使用的变量)并且不要担心锚定类型。