【发布时间】:2020-09-19 07:27:11
【问题描述】:
我在 Microsoft SQL Server 中有一个类似于以下内容的存储过程:
ALTER PROCEDURE [MySchema].[TestTable_MGR_RetrieveLaterThanDate]
@TestDate DATETIME,
@TableData CURSOR VARYING OUTPUT
AS
BEGIN
SET NOCOUNT ON;
SET @TableData = CURSOR FOR
SELECT *
FROM MySchema.TestTable
WHERE @TestDate <= test_date;
OPEN @TableData;
END
我需要从 C# 调用它,但在创建保存输出光标数据所需的 SqlParameter 对象时遇到问题。
我正在创建的参数如下所示:
SqlParameter testDateParameter = new SqlParameter();
testDateParameter.ParameterName = "@TestDate";
testDateParameter.Direction = ParameterDirection.Input;
testDateParameter.SqlDbType = SqlDbType.DateTime;
testDateParameter.Value = theValue;
// I have no idea on what the correct SqlDbType should be here
SqlParameter tableDataParameter = new SqlParameter();
tableDataParameter.ParameterName = "@TableData";
tableDataParameter.Direction = ParameterDirection.Output;
tableDataParameter.SqlDbType = SqlDbType.???;
我已经尝试(对于光标参数)SqlDbType.Udt 和 SqlDbType.Structured,但是在这两种情况下,当调用 SqlCommand 的 ExecuteReader 方法时我都无法得到我想要的结果(两种情况下都有例外)。我尝试了这两个,因为我没有看到任何光标选项。
我知道通常不鼓励使用游标,但.NET 是否根本不允许从 SQL Server 存储过程中读取游标,或者我缺少什么?
提前感谢您的所有帮助。
【问题讨论】:
-
坦率地说,如果这行得通,我会很惊讶,但是:你看到了什么例外?注意:您不会在此处使用 ExecuteReader,因为它实际上并没有发出选择 - 您只需使用 ExecuteNonQuery,但是......您实际上试图在这里 do 做什么?目标是什么?仅 SELECT 会出现什么问题(忘记 CURSOR)?
-
使用 SqlDbType.Udt,您也需要 UdtTypeName,当然“CURSOR”是不允许的(例外是我没有使用 CURSOR 作为 UDT 类型名称的权限)。使用 SqlDbType.Structured,我得到了一个不同的错误:一个是大小(它希望我知道,在执行 sql 命令之前,游标中将包含多少行),另一个是 parameterdirection 输出不是支持 TableData。
-
关于将 CURSOR 替换为 SELECT,这不是我们团队喜欢追求的:我们认为 SQL 代码只能在存储过程中,因此所有 select 语句只允许在存储中程序。不幸的是,这不是我们可以解决的问题。有趣的是,Oracle DLL(DataAccess 和 ManagedDataAccess)都允许使用 RefCursors,而且它们工作得很好,但 SQL Server 出于某种原因却不能。我觉得这非常奇怪。
-
“在存储过程中选择”——当然,没问题;我的意思是,它是主观的、有争议的和上下文相关的,但如果你喜欢它:很好——你喜欢。但这并不能解释为什么要为此使用 CURSOR。这是非常不寻常的,它不会让生活变得轻松。那么:为什么这里有一个 cursor 呢?你试图通过让你的proc直接发出
select而不涉及光标来实现你无法做到的事情是什么?这就是几乎所有 API 的设计预期。这是 ExecuteReader 所期望的,例如,您似乎正在尝试使用哪个 API -
游标在几乎所有方面都受到积极的劝阻,所以:坦率地说,这对我来说并不是一个巨大的震惊;对于常规选择,我认为光标没有任何优点,并且有很多缺点
标签: c# sql-server stored-procedures cursor