2009-03-27 10 views
0

変数を使用してレコード、オブジェクト、または参照カーソルを定義したUser- の動的アクセス・メンバーにアクセスする方法はありますか?例えば。 PL/SQLのユーザー定義オブジェクトのメンバーに動的にアクセスする

get_member(my_object, 'member name'); 

ような何かそれとも

my_object.$'member name'; 

それは私の手順の範囲内で動作しないようIMMEDIATEが動作しませんEXECUTE。

私が達成しようとしていることを巧みに説明しましょう。私はテーブルAのレコードをテーブルBのレコードに変換する方法を記述したマッピングテーブルMを持っています。マッピングはAのレコードの特定のタイプ(Aタイプによって与えられる)によって変わる必要があります。私はこのようなマッピング何かを実行したい(ない正確には、ストリーム関数内のマッピング・ロジックをカプセル化することを計画したが、原理は同様のまま):

SELECT 
    ... 
    CASE 
    WHEN M.field_1_mapping IS NOT NULL THEN 
     -- column of A given by value of M.field_1_mapping 
    ELSE 
     null -- field_1 not filled for record type 
    END field_1, 
    --- etc. 
FROM 
    table_a A, 
    mapping_table M 
WHERE 
    A.TYPE = M.TYPE 

だから私の質問は、私はこれを行う方法です。各レコード・タイプごとに異なる動的SQLを使用することはできませんが、マッピング・フィールドの値に基づいて列を選択できる場合、obovemention SQLは機能します。

私は、PL/SQLの設計理念に反する可能性があることを理解しています。その場合、この問題の解決方法についてお考えの場合は、歓迎します。

P.S:私は:それは単にハードコードマッピング機能例えばすることが可能であろうと仮定

FUNCTION get_field(field_key IN VARCHAR(32), a NOCOPY IN table_a%rowtype) RETURN VARCHAR(2000) IS 
    out VARCHAR2(2000) 
BEGIN 
    -- ... 
    IF field_key = 'field_1' THEN 
    RETURN a.field_1; END IF; 
    -- .. 
END; 

しかし、それは本当に洗練ようです。

答えて

1

ここに、マッピング定義から動的SQLを構築するコードがあります。簡単にするために、EMP表を表Aとして使用し、列DEPTNOがそのタイプとして機能しています。

declare 
    q long; 
    rc sys_refcursor; 
    first boolean := true; 
    l_field1 varchar2(100); 
    l_field2 varchar2(100); 

    function mapcol (p_field_mapping varchar2) return varchar2 
    is 
     l_retval varchar2(32); 
    begin 
     if p_field_mapping is not null then 
     l_retval := 'to_char(a.' || p_field_mapping || ')'; 
     else 
     l_retval := 'null'; 
     end if; 
     return l_retval; 
    end; 
begin 
    -- Construct dynamic SQL 
    for r_map in (select * from mapping_table) 
    loop 
     if first then 
     first := false; 
     else 
     q := q || ' union all '; 
     end if; 
     q := q || 'select '; 
     q := q || mapcol(r_map.field_1_mapping) || ', '; 
     q := q || mapcol(r_map.field_2_mapping); 
     q := q || ' from emp a where a.deptno = ' || r_map.type; 
    end loop; 

    -- Run SQL and show results 
    dbms_output.put_line('SQL = ' || q); 
    dbms_output.put_line(''); 
    dbms_output.put_line('Results'); 
    dbms_output.put_line('-------'); 
    open rc for q; 
    loop 
     fetch rc into l_field1, l_field2; 
     exit when rc%notfound; 
     dbms_output.put_line(l_field1 || ', ' || l_field2); 
    end loop; 
end; 

私は、このマッピングテーブルを作成した:私は(SQL PlusでSERVEROUTPUT ONで)それを実行すると

SQL> create table mapping_table (type integer, 
    2> field_1_mapping varchar2(30), field_2_mapping varchar2(30)); 

Table created. 

SQL> insert into mapping_table values (10, 'ENAME', 'SAL'); 

1 row created. 

SQL> insert into mapping_table values (20, 'SAL', 'JOB'); 

1 row created. 

SQL> insert into mapping_table values (30, 'JOB', 'HIREDATE'); 

1 row created. 

SQL> commit; 

Commit complete. 

は私が取得:

SQL = select to_char(a.ENAME), to_char(a.SAL) from emp a where a.deptno = 10 
union all 
select to_char(a.SAL), to_char(a.JOB) from emp a where a.deptno = 20 
union all 
select to_char(a.JOB), to_char(a.HIREDATE) from emp a where a.deptno = 30 

Results 
------- 
CLARK, 7450 
KING, 10000 
TEST, 
MILLER, 6500 
BINNSY, 100 
FARMER, 123 
7975, MANAGER 
4566, ANALYST 
8000, ANALYST 
5000, janitor 
SALESMAN, 
SALESMAN, 22-FEB-1981 
SALESMAN, 28-SEP-1981 
MANAGER, 01-MAY-1981 
SALESMAN, 08-SEP-1981 
MANAGER, 19-JUL-2008 

PL/SQL procedure successfully completed. 
+0

ええ、それは約行くための方法ですそれ。マッピングテーブルを再構築する必要があり、列順やデータ型チェックなどの改良が必要になります。これをparellizeする方法がありますか? – aggergren

関連する問題