我有一个这样的程序:
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:项目被忽略
请帮我说明如何声明变量。
答案 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
在您可能传递给过程的所有表中使用的所有数据类型。它们都可能适合其中一种基本数据类型 - 即NUMBER
,VARCHAR2(4000)
。
为每种数据类型创建一个单独的过程,调用适当的过程版本(或者,在过程中确定要与逻辑一起使用的变量)并且不要担心锚定类型。