Oracle PL/SQL中的动态类型或泛型
出于某种原因,我在表中有一些字段,它们是字符的集合。不同长度的字符。例如:Oracle PL/SQL中的动态类型或泛型,oracle,generics,plsql,Oracle,Generics,Plsql,出于某种原因,我在表中有一些字段,它们是字符的集合。不同长度的字符。例如: create or replace type t_charray_1 as varray(5) of char(1); create or replace type t_charray_2 as varray(5) of char(2); create or replace type t_charray_3 as varray(5) of char(3); create or replace type t_charray
create or replace type t_charray_1 as varray(5) of char(1);
create or replace type t_charray_2 as varray(5) of char(2);
create or replace type t_charray_3 as varray(5) of char(3);
create or replace type t_charray_4 as varray(5) of char(4);
create table mytable (
field1 number,
field2 t_charray_1,
field3 t_charray_3,
另外,我还有一个函数,它返回mytable
记录的(固定长度)字符串表示形式。此函数调用返回给定集合类型字段的字符串表示形式的其他函数。示例:
function to_chr(
p_array in t_charray_1,
pad_length in number,
p_list_length in number
) return char as
v_res varchar2(255) := '';
begin
for i in 1 .. p_list_length loop
if p_array is not null and p_array.exists(i) and p_array(i) is not null then
v_res := v_res || rpad(p_array(i), pad_length, ' ');
else
v_res := v_res || rpad(' ', pad_length, ' ');
end if;
end loop;
return v_res;
end to_chr;
------------------------------------------------------------------------------
function to_chr(
p_array in t_charray_2,
pad_length in number,
p_list_length in number
) return char as
v_res varchar2(255) := '';
begin
for i in 1 .. p_list_length loop
if p_array is not null and p_array.exists(i) and p_array(i) is not null then
v_res := v_res || rpad(p_array(i), pad_length, ' ');
else
v_res := v_res || rpad(' ', pad_length, ' ');
end if;
end loop;
return v_res;
end to_chr;
请注意,这些函数是彼此的重载版本。它们签名的唯一区别是p_数组
参数的类型
还请注意,这些功能的主体是相同的
动机
我想消除重复代码。我的选择是什么
编辑我听说过sys.anydata,但从未使用过。这是一个解决方案吗?您可以编写一个采用最大类型的过程,并在传递之前将较小的类型显式转换为较大的类型。请注意,强制转换只能在SQL中使用
DECLARE
x t_charray_1 := t_charray_1();
y t_charray_2 := t_charray_2();
PROCEDURE foo( p_foo t_charray_2 )
AS
BEGIN
FOR i IN p_foo.FIRST..p_foo.LAST loop
dbms_output.put_line( p_foo(i) );
END LOOP;
END;
BEGIN
x.EXTEND;
x.EXTEND;
x(1) := 'A';
x(2) := 'B';
y.EXTEND;
y.EXTEND;
y(1) := 'AA';
y(2) := 'BB';
foo(y);
SELECT CAST(x AS t_charray_2) INTO y FROM dual;
foo(y);
END;
/
尝试:
p_数组是如何填充的?你试过创建一个varchar2的varray吗?(并根据需要填充元素)如果我没有不同的集合类型,而是有一个(比如说,最大的一个),那么这将是一个解决方案。但是需要不同的类型,因为它们保证例如field1不能包含长度大于1的值。
create or replace function to_chr(p_array in anydata,
pad_length in number,
p_list_length in number) return char as
v_res varchar2(255) := '';
x number;
v_array t_charray_4;
v_array1 t_charray_1;
v_array2 t_charray_2;
v_array3 t_charray_3;
begin
dbms_output.put_line(p_array.GetTypeName);
case p_array.GetTypeName
when '<schema>.T_CHARRAY_1' then
x := p_array.GetCollection(v_array1);
select cast(v_array1 as t_charray_4) into v_array from dual;
when '<schema>.T_CHARRAY_2' then
x := p_array.GetCollection(v_array2);
select cast(v_array2 as t_charray_4) into v_array from dual;
when '<schema>.T_CHARRAY_3' then
x := p_array.GetCollection(v_array3);
select cast(v_array3 as t_charray_4) into v_array from dual;
when '<schema>.T_CHARRAY_4' then
x := p_array.GetCollection(v_array);
end case;
for i in 1 .. p_list_length loop
if v_array is not null and v_array.exists(i) and v_array(i) is not null then
v_res := v_res || rpad(v_array(i), pad_length, ' ');
else
v_res := v_res || rpad(' ', pad_length, ' ');
end if;
end loop;
return v_res;
end to_chr;
declare
p_array anydata;
v_array t_charray_3 := new t_charray_3('aaa', 'bbb');
v_res varchar2(255);
begin
p_array := anydata.convertcollection(v_array);
v_res := to_chr(p_array => p_array, pad_length => 2, p_list_length => 3);
end;