2013-02-13 38 views
0

我有以下查詢的Oracle 11g PL/SQL光標,相交查詢

select distinct name from table1 
intersect 
select distinct name from table2; 

我的結果集加載到光標的PL/SQL程序中,像這樣:

cursor c1 is (select distinct name from table1 
intersect 
select distinct name from table2); 

對於一些原因結果集中的最後一個值在遊標中重複。這在運行查詢本身時不會發生。任何想法爲什麼發生這種情況?

代碼迴路:

var table.col%type; 

BEGIN 
OPEN c1; 
LOOP  
BEGIN 
    exit when c1%NOTFOUND; 
    FETCH c1 into var;  
    INSERT INTO table values (col1, var); 
    commit; 
EXCEPTION 
WHEN DUP_VAL_ON_INDEX THEN   
CONTINUE; 
END; 
END LOOP;  
END; 
+0

它是一個SQL集操作,它只從兩個不同的SELECT語句中選擇公共元素 – user2001117 2013-02-13 04:06:35

+3

你如何循環遊標?你能告訴我們一些代碼嗎? – 2013-02-13 05:11:10

+0

循環代碼添加到問題中。在我運行該過程後,當我查詢數據被插入到的表時,最後的值被插入兩次。 – sotn 2013-02-13 09:30:15

回答

2

EXIT WHEN ..條款應該來FETCH後。假設你的光標有10條記錄要返回。在第一次讀取之前,%NOTFOUND求值爲NULL,處理進入下一個語句,在你的情況下爲FETCH。現在,如果我們快進到第10次迭代,FETCH將獲得第10條記錄,並將相同的內容插入到目標表中。循環將繼續前進,並且由於您的EXIT WHEN %NOTFOUND在獲取之前,它仍然具有上次迭代的值,並且它使控件向前移動,並且在那裏,獲取將無法獲取任何記錄,但代碼無論如何會插入它在第10次迭代中檢索到的最後一行。現在,下一個循環,c1%NOTFOUND將進行評估,以TRUE循環將終止

var table.col%type; 

BEGIN 
OPEN c1; 
LOOP  
BEGIN 

FETCH c1 into var;  
exit when c1%NOTFOUND;  
INSERT INTO table values (col1, var); 
commit; 
EXCEPTION 
WHEN DUP_VAL_ON_INDEX THEN   
CONTINUE; 
END; 
END LOOP;  
END; 
-2

這是典型的你明確的遊標看到的問題。

您的第一選擇應該是單個SQL語句,僅此而已。如果你不得不使用遊標,你應該儘可能使用隱式遊標。

+1

-1這不是顯式遊標的問題,這是因爲使用顯式遊標的方式。雖然同意這種觀點,「首選應該是單個SQL語句」。 – 2013-02-14 01:44:57

+0

任何技術都可以使用得很好或很差,Jeffrey和顯式遊標也不例外。與隱式遊標相比,它們需要更多的邏輯,更多的代碼,它們在很多情況下速度較慢,並且總是更容易出現編碼錯誤。即使是寫得很好的顯式遊標通常也比隱式遊標更慢更劣。 http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:1205168148688 – 2013-02-14 08:42:24

+0

我對此毫無爭議;但是你的帖子並不是問題的答案(「爲什麼會發生這種情況」),所以作爲評論會更合適。 – 2013-02-15 02:49:44