今天 在項目中看一個存儲過程的時候,發現同事寫的之前的有些邏輯錯誤,可能這個錯誤比較典型吧 拿出來分享一下,不使用公司的
數據庫,所以在自己的機子上模擬了一下這個場景。OK
首先,就是2個表,
表temp1,包括id1,val1,2個字段,
表temp2,包括id2,val2 2個字段。
首先,情景大致是這樣的,2個表的ID是有關聯的,就是把temp2中包含的temp1的id的數據,在temp1中把val1都設置為1,不包含的設置為0.
首先,發一下之前錯誤的存儲過程。
create or replace procedure mysdtest as cursor te_v1 is select id1,val1 from Temp1; cursor te_v2 is select id2,val2 from Temp2; v1_t te_v1%rowtype; v2_t te_v2%rowtype; begin open te_v1; loop fetch te_v1 into v1_t; exit when te_v1%notfound; open te_v2; loop fetch te_v2 into v2_t; exit when te_v2%notfound; if v1_t.id1=v2_t.id2 then update temp1 set val1='1' where id1=v1_t.id1; else update temp1 set val1='0' where id1=v1_t.id1; end if; end loop; close te_v2; end loop; close te_v1; end; |
這樣寫邏輯是存在問題的,2層循環,結果就會發現都是0,仔細讀一下程序就會發現問題
比如說有一個值 t1 在表temp1中有值,應該更新val1為1,但是遍歷到下一個t2時,此時t1不符合,然后就執行else 那么t1的val1就又變回了0,所以,程序執行完,都執行了else里面的,當然就錯了。
正確的寫法很多種,這里我就以設置帶參數的游標為例,將2個游標建立關系,再進行遍歷就不會出現問題。
如下:
create or replace procedure myt as cursor te_v1 is select id1,val1 from Temp1; cursor te_v2(idv2 varchar2) is select count(*) from temp2 where id2=idv2; v1_t te_v1%rowtype; numv varchar2(2); begin open te_v1; loop fetch te_v1 into v1_t; exit when te_v1%notfound; open te_v2(v1_t.id1); fetch te_v2 into numv; if numv=0 then update TEMP1 set val1='0' where id1=v1_t.id1; else update TEMP1 set val1='1' where id1=v1_t.id1; end if; close te_v2; end loop; close te_v1; end; |
ok,這種問題我們應該注意到