How use SYS_REFCURSUR in select for update in pl/sql

匿名 (未验证) 提交于 2019-12-03 01:44:01

问题:

I want to select multiple rows and also update all selected rows. so this goal i wrote this query. but when execute it throw exception.

I wrote this query in a producer like bellow.

PROCEDURE get_rows(    a_cursor OUT SYS_REFCURSOR,    a_id IN VARCHAR,    a_count IN NUMBER);  

exception detail:

java.sql.SQLException: ORA-01002: fetch out of sequence

a_cursor is SYS_REFCURSOR

OPEN a_cursor FOR   SELECT mytable.VID   FROM   mytable   WHERE  ROWNUM <= COUNT FOR UPDATE;  loop    FETCH a_cursor INTO a_id;   if a_cursor %notfound then     cnumber := 9999;   else     UPDATE mytable SET     ...     WHERE  VID = a_vid;     COMMIT;   end if; end loop; 

回答1:

A sys_refcursor cannot be used in update statement. You can use an explicit cursor as shown below. Use this way:

    DECLARE     cursor a_cursor is       SELECT mytable.VID       FROM   mytable       WHERE  ROWNUM <= COUNT FOR UPDATE;      a_id number;     begin     OPEN a_cursor;     loop            FETCH a_cursor INTO a_id;                 exit when a_cursor%notfound;           UPDATE mytable SET         ...         WHERE  VID = a_vid;                        end loop;     COMMIT;    close a_cursor;  end; 

Edit:

create or replace PROCEDURE get_rows(                                    a_cursor OUT SYS_REFCURSOR,                                    a_id IN VARCHAR,                                    a_count IN NUMBER) IS                                    cursor a_cur is   SELECT mytable.VID   FROM   mytable   WHERE  ROWNUM <= a_COUNT ;  a_id NUMBER; cnumber number; BEGIN  OPEN a_cur;   LOOP   FETCH a_cur INTO a_id;     IF a_cur%notfound THEN    cnumber := 9999;   End if;    exit when a_cursor%notfound;       UPDATE mytable SET      ...     WHERE  VID = a_vid;   END loop;   COMMIT;       CLOSE a_cur;    Open a_cursor for select * from mytable;  end ; 


回答2:

If you are not doing any other processing in the loop, you can use a MERGE statement instead of a cursor:

SQL Fiddle

Oracle 11g R2 Schema Setup:

CREATE TABLE mytable ( vid, columna ) AS SELECT 1, 'a' FROM DUAL UNION ALL SELECT 2, 'a' FROM DUAL UNION ALL SELECT 3, 'a' FROM DUAL UNION ALL SELECT 4, 'a' FROM DUAL UNION ALL SELECT 5, 'a' FROM DUAL UNION ALL SELECT 6, 'a' FROM DUAL; 

Query 1:

MERGE INTO mytable dst USING (   SELECT VID /* or ROWID AS rid */   FROM   mytable   WHERE  ROWNUM <= 3 ) src ON ( src.VID = dst.VID /* or src.RID = dst.ROWID */ ) WHEN MATCHED THEN   UPDATE SET     columna = 'b' 

Query 2:

SELECT * FROM mytable 

Results:

| VID | COLUMNA | |-----|---------| |   1 |       b | |   2 |       b | |   3 |       b | |   4 |       a | |   5 |       a | |   6 |       a | 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!