我可以在过程中传递光标吗?
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)
我该怎么做。
我假设您正在使用 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 列特定类型。 如果您希望能够将 any 游标传递给过程,那么您需要考虑使用 DBMS_SQL 包(这并不简单!)
来自 MSDN (SQL Server 2008):游标数据类型只能用于 OUTPUT 参数。当指定游标数据类型时,还必须指定 VARYING 和 OUTPUT 关键字。您可以使用游标数据类型指定多个输出参数。
这在MSSQL2005中是不可能的。 我不知道2008年或其他平台。
我已经好几次想这么做了。 它将支持更加模块化的架构。 我可以有一个对数据集执行常见过程的过程,但能够从各种其他过程将光标传递到该数据集。
建议使用视图的答案假设其目的是能够使用同一查询的结果执行两种不同的算法。 当然,这是传递游标的一种用途,但对我来说,我想使用两个不同查询的结果执行相同的算法。 我有两个过程,每个过程都有自己的目的和一个有意义的名称,它们碰巧共享基于不同查询的相同算法,因此每个过程都会使用适当的查询打开游标,然后调用通用过程来执行算法。
那么,为什么不以文本形式传入查询的 SQL,让内部过程在那里打开游标呢? 因为如果您这样做并且 SQL 有任何绑定变量,您需要将它们与文本一起传递,这意味着两个(或更多)查询不仅需要返回相同的列集,而且还必须采用相同的编号和绑定变量的类型。 如果您传递游标,则游标将打开,变量将绑定在声明 SQL 的过程的上下文中,但行将在游标传递到的过程的上下文中进行处理。
对于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