我可以在程序中传递光标吗?

时间:2008-12-15 13:20:26

标签: sql

我可以在程序中传递光标吗?

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 个答案:

答案 0 :(得分:12)

我假设您使用的是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 :(得分:1)

From MSDN(SQL Server 2008):游标数据类型只能用于OUTPUT参数。指定游标数据类型时,还必须指定VARYING和OUTPUT关键字。您可以使用游标数据类型指定多个输出参数。

答案 2 :(得分:0)

关于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

答案 3 :(得分:0)

建议可能使用视图的答案假设意图是能够使用相同查询的结果执行两种不同的算法。当然这是传递光标的一种用法,但对我来说,我想用两个不同查询的结果执行相同的算法。我有两个程序,每个程序都有自己的目的和一个有意义的名称,碰巧根据不同的查询共享相同的算法,所以每个程序都会用适当的查询打开游标,然后调用一个通用程序来执行算法。

那么,为什么不传入查询的SQL,因为文本有内部过程在那里打开光标?因为如果你这样做并且SQL有任何绑定变量,你需要将它们与文本一起传递,这意味着两个(或更多)查询不仅需要返回同一组列,它们还必须使用相同的数字和绑定变量的类型。如果传递光标而不是光标打开,并且变量绑定在声明SQL的过程的上下文中,但是在传递光标的过程的上下文中处理的行。

答案 4 :(得分:-1)

在MSSQL2005中无法实现。我不知道2008或其他平台。

有几次我想这样做。它将支持更模块化的架构。我可以有一个proc,它在数据集上执行一个公共过程,但能够将光标从各种其他过程传递给该数据集。