2016-07-19 112 views
0

我已經嵌套for循環迭代相同的表。在內循環中,我更新了同一個表中的一列。但是,在for循環條件中,我檢查更新的列,我需要不是在開始時動態檢查此列,所以我的循環迭代可能會大大減少。oracle中for循環語句的update語句是否有任何影響?

我這樣做是正確的還是for語句不會看到更新的列?

declare 
control number(1); 
dup number(10); 
res varchar2(5);--TRUE or FALSE 

BEGIN 
dup :=0; 
control :=0; 
FOR aRow IN (SELECT MI_PRINX, geoloc,durum, ROWID FROM ORAHAN where durum=0)  
LOOP 
FOR bRow IN (SELECT MI_PRINX, geoloc, ROWID FROM ORAHAN WHERE ROWID>aRow.ROWID AND durum=0) 
    LOOP 
    BEGIN 
     --dbms_output.put_line('aRow' || aRow.Mi_Prinx || ' bRow' || bRow.Mi_Prinx); 
    select SDO_GEOM.RELATE(aRow.geoloc,'anyinteract', bRow.Geoloc,0.02) into res from dual; 
    if (res='TRUE') 
     THEN 
     Insert INTO ORAHANCROSSES values (aRow.MI_PRINX,bRow.MI_PRINX); 
     UPDATE ORAHAN SET DURUM=1 where rowid=bRow.Rowid; 
     control :=1; 
     --dbms_output.put_line(' added'); 
    END IF; 
    EXCEPTION 
     WHEN DUP_VAL_ON_INDEX 
     THEN 
      dup := dup+1; 
      --dbms_output.put_line('duplicate'); 
      --continue; 
    END; 
    END LOOP; 
    IF(control =1) 
    THEN 
     UPDATE ORAHAN SET DURUM=1 WHERE rowid=aRow.Rowid; 
    END IF; 
    control :=0; 
END LOOP; 
dbms_output.put_line('duplicate: '||dup); 
END ; 

注:我使用Oracle 11g和PL/SQL開發 對不起我的英語。

+0

你試圖通過'ROWID> aRow.ROWID'實現什麼? Oracle中的「ROWID」是一個(或多或少)隨機字符串。未確定'ROWID> aRow.ROWID'的結果。除非您鎖定記錄,否則給定記錄的ROWID甚至可能會更改。但是,手動鎖定行通常是不好的做法。 –

+0

我意識到我在使用rowid時出錯了。我的目的是在外部循環中逐個檢查所有行,在內部循環中,我只需要從外部循環中的選定行中檢查更多的行。 –

回答

1

是的,FOR語句不會看到更新的DURUM列,因爲FOR語句將會看到所有數據與查詢開始時的狀態!這稱爲讀取一致性,Oracle通過使用生成的UNDO數據完成此操作。這意味着它會有越來越多的工作要做(==運行速度較慢),因爲FOR循環前進並更新了基表!

這也意味着當UNDO表空間耗盡時,您的實現最終會遇到ORA-01555:快照太舊的錯誤。

您可能會更好使用SQL MERGE語句,該語句也應該運行得更快。

如:

Merge Into ORAHANCROSSES C 
Using (Select aROW.MI_PRINX aROW_MI_PRIX, 
       aROW.GEOLOC aROW_GEOLOC, 
       bROW.MI_PRINX bROW_MI_PRIX, 
       bROW.GEOLOC bROW_GEOLOC, 
       SDO_GEOM.RELATE(aRow.geoloc,'anyinteract', bRow.Geoloc,0.02) RES 
     From ORAHAN aROW, 
       ORAHAN bROW 
     Where aROW.ROWID < bROW.ROWID 
     ) Q 
On (C.MI_PRIX1 = Q.aROW_MI_PRIX 
    and C.MI_PRIX2 = Q.bROW_MI_PRIX) 
When Matched Then 
    Delete Where Q.RES = 'FALSE' 
When Not Matched Then 
    Insert Values (Q.aROW_MI_PRIX, Q.bROW_MI_PRIX) 
    Where Q.RES = 'TRUE' 
; 

我不知道你要完成由ROWID>aRow.ROWID雖然

要使用一定的順序(在這種情況下MI_PRINX)有什麼用以下方法:

Merge Into ORAHANCROSSES C 
Using (With D as (select T.*, ROWNUM RN from (select MI_PRINX, GEOLOC from ORAHAN order by MI_PRINX) T) 
     Select aROW.MI_PRINX aROW_MI_PRIX, 
       aROW.GEOLOC aROW_GEOLOC, 
       bROW.MI_PRINX bROW_MI_PRIX, 
       bROW.GEOLOC bROW_GEOLOC, 
       SDO_GEOM.RELATE(aRow.geoloc,'anyinteract', bRow.Geoloc,0.02) RES 
     From D aROW, 
       D bROW 
     Where aROW.RN < bROW.RN 
     ) Q 
On (C.MI_PRIX1 = Q.aROW_MI_PRIX 
    and C.MI_PRIX2 = Q.bROW_MI_PRIX) 
When Matched Then 
    Delete Where Q.RES = 'FALSE' 
When Not Matched Then 
    Insert Values (Q.aROW_MI_PRIX, Q.bROW_MI_PRIX) 
    Where Q.RES = 'TRUE' 
; 

如果查詢時間過長,您可能需要select * from v$session_longops where seconds_remaining >0來確定它何時完成。

+0

我必須在外層循環中逐一循環所有行。但在內部循環中,我只需要檢查更多的行(大於外部row.ID)。我想我使用rownum或者什麼?更新語句是否在merge語句中工作? –

+0

我添加了「哪裏aROW.ROWID

+0

我的表有大約40萬條記錄,我等待50分鐘執行,但沒有結束。任何建議? –