проблема определения слабо определенного курсора ссылки - PullRequest
2 голосов
/ 17 июня 2009

Я пытаюсь написать сохраненный процесс, который принимает число n и возвращает первые n результатов для данного запроса, блокируя исключительно эти n строк. Я немного новичок в SQL, и у меня возникли сложности с правильным сопоставлением типов данных.

Моя спецификация пакета выглядит следующим образом:

PACKAGE package IS
   Type out_result_type is REF CURSOR;
   PROCEDURE stored_proc
     (in_n IN NUMBER DEFAULT 10, 
        out_list IN OUT out_result_type);

Затем я определяю курсор в теле процедуры, например:

CURSOR OUT_RESULT_TYPE IS
        SELECT a.id
            FROM schema.table a
            WHERE (some conditions) AND rownum <= in_n;

Чуть позже я пытаюсь извлечь результаты курсора в выходную переменную:

OPEN OUT_RESULT_TYPE;
FETCH OUT_RESULT_TYPE INTO out_list; -- error on this line
CLOSE OUT_RESULT_TYPE;

Но, увы, этот код не компилируется; оракул жалуется, что out_list уже был определен с конфликтующим типом данных. Любая идея, как я могу решить эту проблему? Это сводит меня с ума!

Заранее спасибо.

Ответы [ 5 ]

1 голос
/ 17 июня 2009
CREATE OR REPLACE PACKAGE pkg_test
AS
        TYPE    tt_cur IS REF CURSOR;
        PROCEDURE prc_cur (retval OUT tt_cur);
END;

CREATE OR REPLACE PACKAGE BODY pkg_test
AS
        PROCEDURE prc_cur (retval OUT tt_cur)
        AS
        BEGIN
                OPEN    retval
                FOR
                SELECT  *
                FROM    dual;
        END;
END;

Если вы хотите заблокировать, используйте:

CREATE OR REPLACE PACKAGE BODY pkg_test
AS
        PROCEDURE prc_cur (retval OUT tt_cur)
        AS
        BEGIN
                OPEN    retval
                FOR
                SELECT  a.id
                FROM    schema.table a
                WHERE   (some conditions)
                        AND rownum <= in_n
                ORDER BY
                        column
                -- Never forget ORDER BY!
                FOR UPDATE;
        END;
END;
0 голосов
/ 19 июня 2009

Oracle предоставляет предопределенный курсор со слабой ссылкой: sys_refcursor. В использовании это будет выглядеть так:

CREATE OR REPLACE PACKAGE pkg_test
AS
    PROCEDURE prc_cur (p_retval OUT sys_refcursor,
                       p_lookup IN  VARCHAR2);
END pkg_test;


CREATE OR REPLACE PACKAGE BODY pkg_test 
AS
    PROCEDURE prc_cur(p_retval OUT sys_refcursor
                      p_lookup IN  VARCHAR2) 
    IS
    BEGIN
        OPEN retval FOR SELECT a.value 
                          FROM tblname a 
                         WHERE a.id <= p_lookup;
    END prc_cur;
END pkg_test;

Это избавляет вас от необходимости объявлять тип. Sys_refcursor - это указатель на набор результатов из открытого курсора. Если вы знакомы с Java, это та же концепция, что и у объекта java.sql.ResultSet, который позволяет получить результаты запроса.

0 голосов
/ 17 июня 2009

Это не сработает так, как написано, потому что

  1. out_list ожидает курсор, а не результат курсора.
  2. Имя out_result_type уже используется для типа , поэтому вы не можете переопределить его как курсор в той же области.
0 голосов
/ 17 июня 2009

Два замечания:

  1. Курсор не блокируется.
  2. Вам не нужно делать Type out_result_type is REF CURSOR;, используйте тип по умолчанию sys_refcursor. Смотрите здесь: Oracle - Как получить параметр курсора out ref в хранимой процедуре?
0 голосов
/ 17 июня 2009

Ваш out_list должен быть неправильного типа. Рассмотрим (скрипт запускается на 10.2.0.3):

CREATE TABLE t AS SELECT ROWNUM ID FROM all_objects WHERE ROWNUM <= 100;

CREATE OR REPLACE PACKAGE cursor_pck AS
   TYPE out_result_type is REF CURSOR;
   PROCEDURE stored_proc (p_in IN NUMBER DEFAULT 10, 
                          p_out_list IN OUT out_result_type);
END cursor_pck;
/

Если вы хотите выбрать и заблокировать строки одновременно, вы должны использовать предложение FOR UPDATE:

CREATE OR REPLACE PACKAGE BODY cursor_pck AS
   PROCEDURE stored_proc (p_in IN NUMBER DEFAULT 10,  
                          p_out_list IN OUT out_result_type) IS
   BEGIN
      OPEN p_out_list FOR SELECT a.id FROM t a WHERE ROWNUM <= p_in FOR UPDATE;
   END stored_proc;
END cursor_pck;
/

При следующей настройке вы вызовете процедуру следующим образом:

SQL> SET SERVEROUTPUT ON;
SQL> DECLARE
  2     l_cursor cursor_pck.out_result_type;
  3     l_id t.id%TYPE;
  4  BEGIN
  5     cursor_pck.stored_proc(3, l_cursor);
  6     LOOP
  7        FETCH l_cursor INTO l_id;
  8        EXIT WHEN l_cursor%NOTFOUND;
  9        dbms_output.put_line(l_id);
 10     END LOOP;
 11  END;
 12  /

1
2
3

PL/SQL procedure successfully completed
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...