2012-03-01 56 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; 

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