假设我有一个带有主键conf
的表PK
:
Conf
------------------
PK A B C
------------------
1 Y Y Y
2 Y Y
3 Y
------------------
我有另一个表temp:
Temp
------------------
PK A B C
------------------
1 ab cd ef
1 null cd ef
2 cd pq
3 dn
------------------
我需要从conf
表中获取值Y
的列和PK的所有名称,例如:
1 A B C
2 A C
3 A
需要将这些值与temp
表行进行比较,并检查该列中fetched的值是否为null,如果是,则抛出错误。
例如,对于2 A C
,我们需要将2
作为PK
的临时表的A和C列进行比较。
我的问题是如何在光标中获取以下记录:
1 A B C
2 A C
3 A
我没有得到优化的解决方案。可以通过将conf
表的所有列与temp
表进行比较来完成,但可以有超过15列。
算法的大纲是:
fetch all column name from conf table having value 'Y'
loop
fetch all the columns from temp table with primary key from outer cursor
loop
On the basis of column name from outer cursor check the value of column
of temp table for its nullability
end loop;
end loop;
答案 0 :(得分:2)
我认为使用类似的查询更好:
select c.*, t.*
from conf c, temp t
where c.pk = t.pk
and ((c.a = 'Y' and t.a is null) or (c.b = 'Y' and t.b is null) or
(c.c = 'Y' and t.c is null))
如果您不知道列,可以通过循环user_tab_cols / all_tab_cols来动态创建查询:
declare
sql_str varchar2(32767);
cursor c_col is
select tc.column_name
from user_tab_cols tc
where tc.table_name = 'CONF' and tc.column_name <> 'PK';
type rc_bad_rows is ref cursor;
c_bad_rows rc_bad_rows;
val number;
is_first boolean := true;
begin
sql_str := 'select t.pk from conf c, temp t ' ||
'where c.pk = t.pk and (';
for r in c_col loop
if not is_first then
sql_str := sql_str || ' or ';
end if;
is_first := false;
sql_str := sql_str || '(c.' || r.column_name || ' = ''Y'' and t.' ||
r.column_name || ' is null)';
end loop;
sql_str := sql_str || ')';
dbms_output.put_line(sql_str);
open c_bad_rows for sql_str;
loop
fetch c_bad_rows
into val;
exit when c_bad_rows%notfound;
dbms_output.put_line(val);
end loop;
close c_bad_rows;
end;
这段代码可能不是最好的,但它就是一个例子......