2012-10-31 58 views
3

出於某種原因,我有一個表中的某些領域,是字符的集合。不同長度的字符。例如:動態類型或泛型/ SQL

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_array參數的類型。

也請注意,的這些功能機構是相同

動機

我想消除重複的代碼。我的選擇是什麼?

編輯我聽說過sys.anydata,但從來沒有使用它。它可以成爲解決方案嗎?

+0

如何p_array得到填充?具有u嘗試創建VARCHAR2的一個VARRAY? (並根據需要填充元素) – tbone

+0

這將是一個解決方案如果我沒有不同的集合類型,但只有一個(可以說,最大的一個)。但是需要不同的類型,因爲它們保證了例如field1不能包含長度大於1的值。 – bpgergo

回答

2

您可以編寫一個採用最大類型的過程,並在傳遞它們之前將較小類型明確地CAST到較大類型。請注意,CAST只能在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; 
/
+0

感謝您的回覆,我會盡力回覆 – bpgergo

2

嘗試:

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; 
+0

感謝您的回覆,我會盡力回覆。我的第一個想法是 – bpgergo