2012-03-01 59 views
0

取假设我有一个表conf与主键PK复杂的光标

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  
------------------ 

我需要获取列和PK的所有名称来自conf表,其值为Y,例如:

1 A B C 
2 A C 
3 A 

这些值需要与temp表格行进行比较,并检查列中获取的列的值是否为null,如果是,则抛出错误。

例如,对于2 A C,我们需要将具有2的临时表的A和C列与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; 

回答

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; 

此代码可能不是最好的,但它是一个例如...