有没有办法访问用户的动态访问成员 - 使用变量定义记录,对象或引用游标?例如。 像
这样的东西 get_member(my_object, 'member name');
或者
my_object.$'member name';
EXECUTE IMMEDIATE不起作用,因为它不在我的程序范围内操作。
让我巧妙地解释我想要完成的事情。我有一个映射表M,它描述了如何将表A的记录转换成表B的记录。映射必须根据A中的特定记录类型(由A.type给出)而变化。我想执行这样的映射(不完全是,计划在流函数中封装映射逻辑,但原理仍然类似):
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;
但这似乎非常不优雅。
答案 0 :(得分: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> 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 Plus中使用SERVEROUTPUT ON),我得到:
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.