Plsql 从游标获取复杂数据

Plsql 从游标获取复杂数据,plsql,oracle10g,Plsql,Oracle10g,假设我有一个带有主键的表conf: Conf ------------------ PK A B C ------------------ 1 Y Y Y 2 Y Y 3 Y ------------------ 我还有一张临时桌: Temp ------------------ PK A B C ------------------ 1 ab cd ef 1 null cd ef 2

假设我有一个带有主键的表
conf

Conf
------------------
PK  A    B     C
------------------
1   Y    Y     Y
2   Y          Y
3   Y    
------------------
我还有一张临时桌:

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
表行进行比较,并检查获取的列的值在该列中是否为空,如果为空,则抛出错误

例如,对于
2c
,我们需要将temp表的A和C列与
2
as
PK
进行比较

我的问题是如何在游标中获取以下记录:

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;

我认为最好使用如下查询:

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\u tab\u cols/all\u tab\u 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;
声明
sql_str varchar2(32767);
光标c_col为
选择tc.column\u name
从用户选项卡目录tc
其中tc.table_name='CONF'和tc.column_name'PK';
类型rc\u bad\u rows是ref游标;
c_坏_行rc_坏_行;
val数;
第一个布尔值为:=真;
开始
sql_str:=“从配置c、临时t中选择t.pk”||
'其中c.pk=t.pk和(';
对于c_col循环中的r
如果不是,那你是第一个
sql_str:=sql_str | |或‘;
如果结束;
is_first:=false;
sql|str:=sql|str|'(c.| | r.column|u name | |'='Y'和t.'||
r、 列_name | |'为空);
端环;
sql_str:=sql_str | |');
dbms_output.put_行(sql_str);
为sql语句打开c_bad_行;
环
取c_坏_行
进入val;
未找到c_坏_行%n时退出;
dbms_output.put_line(val);
端环;
关闭c_bad_行;
结束;
这段代码可能不是最好的,但它是一个例子