台灣最大程式設計社群網站
線上人數
1035
 
會員總數:246087
討論主題:189663
歡迎您免費加入會員
討論區列表 >> Oracle >> 請問 ORA-01002 擷取的順序不對
[]  
[我要回覆]
1
回應主題 加入我的關注話題 檢舉此篇討論 將提問者加入個人黑名單
請問 ORA-01002 擷取的順序不對
價值 : 70 QP  點閱數:11681 回應數:9
樓主

Justin
門外漢
0 16
290 19
發送站內信

我在執行 procedure 時遇到 ORA-01002 擷取的順序不對的問題,
直覺猜測是因為有使用 cursor 的原因,上網查了一下,
"好像"是因為使用 cursor 下了 for update 語法時,會 lock 住 fetch 的資料,
此時 update 那筆資料會造成 ORA-01002 的錯誤。
但我不太確定是不是這樣,但之前有以類似方式寫過別支 procedure,執行時卻沒這個問題。
請問大家,「ORA-01002 擷取的順序不對」的問題要怎麼解呢?謝謝!

搜尋相關Tags的文章: [ ORA-01002 擷取的順序不對 ] , [ ora ] , [ 01002 ] , [ ora-01002 ] , [ fetch out of ] ,
本篇文章發表於2010-10-13 10:34
1樓
回應

花旗蔘
檢舉此回應
把script 貼上來吧
本篇文章回覆於2010-10-13 13:47
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
2樓
作者回應

Justin
檢舉此回應
有兩個 procedure,P_AAA 會呼叫 P_BBB

CREATE OR REPLACE PROCEDURE P_AAA
IS
CURSOR a_cur IS
SELECT ca,cb
FROM table_a
WHERE cc= 'xxx'
ORDER BY ca,cd
FOR UPDATE;

a_rec a_cur%ROWTYPE;

BEGIN

if not a_cur%ISOPEN then
open a_cur;
end if;

loop
FETCH a_cur INTO a_rec;
EXIT WHEN a_cur%NOTFOUND;

P_BBB(a_cur.ca,a_cur.cb);

end loop;

COMMIT;
END;
/

以下是 P_BBB

CREATE OR REPLACE PROCEDURE P_BBB
(
p_a IN number,
p_b IN number
)

IS
v_a number := p_b;

CURSOR b_cur IS
SELECT ca,cb,cc,cd
FROM table_b
WHERE ca = p_a
ORDER BY cb
FOR UPDATE;

b_rec b_cur%ROWTYPE;

BEGIN

if not b_cur%ISOPEN then
open b_cur;
end if;

loop
FETCH b_cur INTO b_rec;
EXIT WHEN b_cur%NOTFOUND;

if b_rec.cd is not null and b_rec.cd > 0 then
if v_a > 0 then
if b_rec.cd >= v_a then
update table_b
set cc = cc + v_a,
cd = cd - v_a
where ca = p_a
and cb = b_rec.cb;

v_a := 0;
else
v_a := v_a - b_rec.cd;

update table_b
set cd = 0,
cc = ce
where ca = p_a
and cb = b_rec.cb;
end if;
end if;
end if;

end loop;

COMMIT;
END;
/
本篇文章回覆於2010-10-13 14:21
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
3樓
作者回應

Justin
檢舉此回應
沒有人知道怎麼解嗎? >"<
本篇文章回覆於2010-10-14 16:02
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
4樓
回應

花旗蔘
檢舉此回應
你把 P_BBB 的commit 註解掉試試~

本篇文章回覆於2010-10-14 18:51
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
5樓
最有價值解答

花旗蔘
檢舉此回應
其實執行後的錯誤訊息 就有很明顯的訊息了
你p_aaa 在 fetch loop中 呼叫p_bbb 而p_bbb裡面有commit
你原p_aaa的cursor是select for update的
而你在之後的fetch loop 下了commit(p_bbb) 改變了它的狀態,這錯誤由此而來

-----test
create or replace procedure ben.abc
is
cursor p is
select * from dual for update;
b p%ROWTYPE;
begin
open p;
loop
FETCH p INTO b;
EXIT WHEN p%NOTFOUND;
commit;
end loop;
end;

----------------

----執行
execute ben.abc

命令的第 1 行開始發生錯誤:
execute ben.abc
錯誤報告:
ORA-01002: &iquest;&iquest;&iquest;&iquest;&iquest;&iquest;&iquest;
ORA-06512: &iquest; "BEN.ABC", line 9
ORA-06512: &iquest; line 1
01002. 00000 - "fetch out of sequence"
*Cause: This error means that a fetch has been attempted from a cursor
which is no longer valid. Note that a PL/SQL cursor loop
implicitly does fetches, and thus may also cause this error.
There are a number of possible causes for this error, including:
1) Fetching from a cursor after the last row has been retrieved
and the ORA-1403 error returned.
2) If the cursor has been opened with the FOR UPDATE clause,
fetching after a COMMIT has been issued will return the error.
3) Rebinding any placeholders in the SQL statement, then issuing
a fetch before reexecuting the statement.
*Action: 1) Do not issue a fetch statement after the last row has been
retrieved - there are no more rows to fetch.
2) Do not issue a COMMIT inside a fetch loop for a cursor
that has been opened FOR UPDATE.
3) Reexecute the statement after rebinding, then attempt to
fetch again.
本篇文章回覆於2010-10-14 19:34
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
6樓
作者回應

Justin
檢舉此回應
感謝花旗蔘的解釋,我大致瞭解了,我想再請教一個問題確認一下,
是因為我在 p_bbb 有一個 commit,雖然是 p_aaa 呼叫 p_bbb,
但是 p_bbb 裡面執行的 commit 同時也把 p_aaa 裡因 for update 而 lock 住的 cursor 解開,
也就是 p_bbb 的 commit 會同時解開 p_aaa 裡鎖住的 cursor,
導致回到 p_aaa 要再 fetch cursor 時就會錯誤,不知我的理解是否有錯?謝謝!
本篇文章回覆於2010-10-19 12:16
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
7樓
作者回應

Justin
檢舉此回應
補充一下,或者我把 p_aaa 中 cursor 的 for update 這一行拿掉,
也可以解決 ORA-01002 的問題,是嗎?
本篇文章回覆於2010-10-19 14:49
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
8樓
回應

花旗蔘
檢舉此回應
嗯嗯~你把測試的語法run一下就能了解了
本篇文章回覆於2010-10-19 23:43
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
9樓
回應

Youme
檢舉此回應
各位大大好,小弟也遇到相同的fetch out of sequence的問題
但是我的PROCEDURE裡面沒有下for update的語法,
且也有其它PROCEDURE的格式是一樣的,
也有測試一筆是可以執行,但是兩筆以上就不行了,想請問是否有人可以解答。
謝謝。
本篇文章回覆於2013-07-26 16:45
== 簽名檔 ==
--未登入的會員無法查看對方簽名檔--
   
1

回覆
如要回應,請先登入.