Могу ли я передать курсор в процедуре? - PullRequest
9 голосов
/ 15 декабря 2008

можно ли передать курсор в процедуре?

CURSOR  BLT_CURSOR IS
SELECT  BLT.sol_id,
        BLT.bill_id,
        BLT.bank_id
FROM BLT;

Мой курсор.

Procedure abc(i want to pass the cursor here)

Как мне это сделать.

Ответы [ 5 ]

12 голосов
/ 15 декабря 2008

Я предполагаю, что вы используете Oracle (похоже, так).

Вы можете сделать это:

PROCEDURE abc( p_cursor IN SYS_REFCURSOR) IS
   v_sol_id blt.sol_id%TYPE;
   v_bill_id blt.bill_id%TYPE;
   v_bank_id blt.bank_id%TYPE;
BEGIN
   LOOP
      FETCH p_cursor INTO v_sol_id, v_bill_id, v_bank_id;
      EXIT WHEN p_cursor%NOTFOUND;
      ...
   END LOOP;
END;

Тогда используйте это:

DECLARE
   v_cursor SYS_REFCURSOR;
BEGIN
   OPEN v_cursor FOR
      SELECT  BLT.sol_id,
              BLT.bill_id,
              BLT.bank_id
      FROM BLT;
   abc (v_cursor);
   CLOSE v_cursor;
END;

Однако обратите внимание, что процедуре abc необходимо знать структуру курсора, то есть она возвращает 3 столбца определенных типов. Если вы хотите, чтобы в процедуру можно было передать любой курсор, вам нужно рассмотреть использование пакета DBMS_SQL (и это не тривиально!)

1 голос
/ 15 декабря 2008

С MSDN (SQL Server 2008): тип данных курсора можно использовать только для параметров OUTPUT. При указании типа данных курсора также должны быть указаны ключевые слова VARYING и OUTPUT. Для типа данных курсора можно указать несколько выходных параметров.

0 голосов
/ 18 ноября 2018

Что касается MS-SQL, вы не можете передать курсор в качестве входного параметра. Вы можете передать курсор только в качестве выходного параметра.
Что вы можете сделать, это передать текст предложения выбора курсора в качестве входного параметра. Вы можете найти рабочий фрагмент кода ниже полезным.

--Create the table and fill it with data
DROP   TABLE    dbo.StackOverflow_MyTable
GO
CREATE TABLE    dbo.StackOverflow_MyTable (
                MyChar      varchar(10),
                MyDate      datetime,
                MyNum       numeric(10,2)
                PRIMARY KEY (MyChar))
GO
INSERT INTO dbo.StackOverflow_MyTable SELECT 'A1', '2018-01-13', 123.45
INSERT INTO dbo.StackOverflow_MyTable SELECT 'B2', '2018-01-14', 123.46
INSERT INTO dbo.StackOverflow_MyTable SELECT 'C3', '2018-01-15', 123.47
GO
/* Create the procedure which returns the cursor variable based on select statement
   The cursor must be opened here. Otherwise it throws an Error:
   The variable '@MyCursorVar' does not currently have a cursor allocated to it
*/
DROP   PROCEDURE dbo.StackOverflow_OpenCursor
GO
CREATE PROCEDURE dbo.StackOverflow_OpenCursor @SelectSQL nvarchar(128), @MyCursorVar CURSOR VARYING OUTPUT
    AS
    DECLARE @SQL nvarchar(256)
    SET @SQL='  SET     @MyCursorVar = CURSOR FOR '+@SelectSQL+'
                OPEN    @MyCursorVar'

    EXEC sp_executesql @SQL, N'@MyCursorVar CURSOR OUTPUT', @MyCursorVar OUTPUT
GO

--Create the procedure which browses the table using the cursor variable
DROP   PROCEDURE dbo.StackOverflow_BrowseCursor
GO
CREATE PROCEDURE dbo.StackOverflow_BrowseCursor @SelectSQL nvarchar(128)
    AS
    --Create the cursor variable based on select statement and OPEN the cursor
    DECLARE @MyCursorVar CURSOR
    EXEC dbo.StackOverflow_OpenCursor @SelectSQL, @MyCursorVar OUTPUT

    --Declare the variables corresponding to table column
    DECLARE @MyChar varchar(10), @MyDate datetime, @MyNum numeric(10,2)
    --Browse record by record
    WHILE 1=1
    BEGIN
        FETCH NEXT FROM @MyCursorVar INTO @MyChar, @MyDate, @MyNum
        IF @@FETCH_STATUS <> 0 BREAK
        PRINT @MyChar   --Here you might call any other procedure or dataset update
        PRINT @MyDate
        PRINT @MyNum
    END
    --release the cursor resources
    CLOSE       @MyCursorVar
    DEALLOCATE  @MyCursorVar
GO

--How to call the cursor browsing 
DECLARE @SelectSQL nvarchar(128)
SET     @SelectSQL = 'SELECT MyChar, MyDate, MyNum FROM dbo.StackOverflow_MyTable ORDER BY MyChar'
EXEC dbo.StackOverflow_BrowseCursor @SelectSQL
0 голосов
/ 11 апреля 2012

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

Итак, почему бы не передать SQL запроса, так как текст имеет внутреннюю процедуру, открывающую курсор там? Потому что, если вы сделаете это, и в SQL есть какие-либо связанные переменные, вам нужно будет передать их вместе с текстом, что означает, что два (или более) запроса должны не только возвращать один и тот же набор столбцов, но и принимать одинаковое число. и типы связанных переменных. Если вместо этого вы передаете курсор, курсор открывается и переменные связываются в контексте процедуры, в которой объявлен SQL, но строки обрабатываются в контексте процедуры, в которую передается курсор.

0 голосов
/ 15 декабря 2008

Это невозможно в MSSQL2005. Я не знаю о 2008 или других платформах.

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

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