如何在pl / sql中选择更新时使用SYS_REFCURSUR

时间:2018-05-29 09:41:08

标签: sql oracle plsql

我想选择多行并更新所有选定的行。所以这个目标我写了这个查询。但是当执行它时会抛出异常。

我在像bellow这样的制片人中写过这个问题。

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

异常细节:

  

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

a_cursor是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;

2 个答案:

答案 0 :(得分:2)

sys_refcursor语句中无法使用update。您可以使用显式游标,如下所示。使用这种方式:

    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;

编辑:

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 ;

答案 1 :(得分:2)

如果你没有在循环中进行任何其他处理,你可以使用MERGE语句而不是游标:

SQL Fiddle

Oracle 11g R2架构设置

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;

查询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'

查询2

SELECT * FROM mytable

<强> Results

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