【问题标题】:OdbcParameter error - size of 0 for varchar(MAX) output parameterOdbcParameter 错误 - varchar(MAX) 输出参数的大小为 0
【发布时间】:2017-11-13 14:04:17
【问题描述】:

我正在使用:

Microsoft SQL Server 2012 (SP1) - 11.0.3128.0 (X64) 2012 年 12 月 28 日 20:23:12
版权所有 (c) Windows NT 6.2 (Build 9200: ) (Hypervisor) 上的 Microsoft Corporation Enterprise Edition(64 位)

我有一个存储过程,它有一个varchar(MAX) 输出参数。

我通过OdbcCommand 调用它,并创建了VarChar 输出参数并将其添加到OdbcCommand Parameters 列表中:

new OdbcParameter("@MaxField", OdbcType.VarChar)
    { Direction = ParameterDirection.Output, Size = -1 })

在调试时,我可以看到参数上的 Size 字段仍然是 -1,但是当我使用 OdbcCommand.ExecuteNonQuery() 运行查询时,出现以下异常:

System.InvalidOperationException 未处理
HResult=-2146233079
Message=String[2]:Size 属性的大小为 0 无效。
源=System.Data
堆栈跟踪:
在 System.Data.Odbc.OdbcParameter.GetParameterSize(对象值,Int32 偏移量,Int32 序数)
在 System.Data.Odbc.OdbcParameter.PrepareForBind(OdbcCommand 命令,Int16 序数,Int32& parameterBufferSize)
在 System.Data.Odbc.OdbcParameterCollection.CalcParameterBufferSize(OdbcCommand 命令)
在 System.Data.Odbc.OdbcCommand.ExecuteReaderObject(CommandBehavior 行为,字符串方法,布尔需要读取器,对象[] 方法参数, SQL_API odbcApiMethod)
在 System.Data.Odbc.OdbcCommand.ExecuteReaderObject(CommandBehavior 行为,字符串方法,布尔需要Reader)
在 System.Data.Odbc.OdbcCommand.ExecuteNonQuery()

我尝试使用OdbcCommandBuilder.DeriveParameters(odbcCommand); 检查从存储过程派生的参数信息,它说该参数的大小为 2147483647 - 但是,如果我尝试使用该值,我会得到另一个例外告诉我

System.Data.Odbc.OdbcException 未处理
错误代码=-2146232009
HResult=-2146232009
Message=ERROR [42000] [Microsoft][ODBC SQLServer Driver][SQL Server]无效参数 2 (''): 数据类型 0x23 是 不推荐使用的大对象或 LOB,但被标记为输出参数。 不支持将不推荐使用的类型作为输出参数。使用电流 而是大对象类型。源=SQLSRV32.DLL StackTrace:
在 System.Data.Odbc.OdbcConnection.HandleError(OdbcHandle hrHandle, RetCode retcode)
在 System.Data.Odbc.OdbcCommand.ExecuteReaderObject(CommandBehavior 行为,字符串方法,布尔需要读取器,对象[] 方法参数, SQL_API odbcApiMethod)
在 System.Data.Odbc.OdbcCommand.ExecuteReaderObject(CommandBehavior 行为,字符串方法,布尔需要Reader)
在 System.Data.Odbc.OdbcCommand.ExecuteNonQuery()

我应该如何配置我的 OdbcCommand 输出参数以接收来自存储过程的输出?

这是在现有的生产数据库上,因此很遗憾,尝试更改字段的数据类型是绝对的最后手段。正在选择的字段是varchar(max)

编辑:如果实际答案是“你不能”,那么这是可以接受的——至少我可以肯定地知道。

【问题讨论】:

  • 您需要为输出参数使用合理的大小。 2147483647 太大。您希望您的存储过程返回什么值?
  • 该字段定义为varchar(max) - 它将能够保存任何适合的值。 2147483647 的值来自 OdbcCommandBuilder
  • @RacilHilan 这个问题 - stackoverflow.com/questions/973260/… - 有一个公认的答案,说明 -1 是用于 varchar(max)size,但这是在输入参数上。我正在尝试研究如何使 varchar(max) 输出参数正常工作。
  • 我明白,但即使你让它工作,那也是一个糟糕的设计。检查返回的值并相应地使用合理的大小。
  • @RacilHilan 让我这样说 - 在 varchar(max) 字段中,认为它会有多大?

标签: c# sql-server stored-procedures odbc


【解决方案1】:

如果您想坚持使用System.Data.Odbc,那么以下解决方法可能就足够了。对于存储过程

CREATE PROCEDURE [dbo].[HodorSpeaks] 
    @repeat int = 1, 
    @response varchar(max) OUTPUT
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @whatHeSaid varchar(max);
    SET @whatHeSaid = 'HODOR! ';
    SELECT @response = REPLICATE(@whatHeSaid, @repeat);
END

C# 代码

using (var cmd = new OdbcCommand())
{
    cmd.Connection = conn;
    cmd.CommandType = System.Data.CommandType.Text;
    cmd.CommandText = 
        "SET NOCOUNT ON; " +
        "DECLARE @out varchar(max); " +
        "EXEC dbo.HodorSpeaks @repeat=?, @response=@out OUTPUT; " +
        "SELECT @out;";
    cmd.Parameters.Add("?", OdbcType.Int).Value = 10000;
    string resp = cmd.ExecuteScalar().ToString();
    Console.WriteLine("{0} characters were returned", resp.Length);

}

告诉我

70000 characters were returned

【讨论】:

  • 非常有趣,而且非常狡猾。但我想我将不得不接受,试图让它“优雅”地工作是一个渺茫的希望。
  • 避免声明输出参数的好技巧。不优雅,但简单且有效。 +1
【解决方案2】:

varchar(max) 在 SQL Server 2005 中引入以替换 text 类型。当值小于 8000 时,它像标准的varchar(n) 一样存储在页面上,而高于 8000 的值则像 text 一样存储在页面外。

不推荐使用textvarcha(max)作为参数,正如消息告诉你的,它甚至不支持输出参数:

数据类型 0x23 是不推荐使用的大对象或 LOB,但被标记为输出参数。不支持将不推荐使用的类型作为输出参数。请改用当前的大型对象类型。

最好的解决方案是修复存储过程并将输出参数从varchar(max)更改为varchar(n)。否则,您可以在代码中为参数使用varchar(8000),并希望存储过程永远不会返回超过8000 的值。值8000 是varchar(n) 类型的最大值。

此外,您可以通过使用不抱怨使用varchar(max) 作为输出参数的不同(旧)版本的 ODBC 驱动程序来解决它,但这显然不是最好的方法。

【讨论】:

  • 感谢您根据您的 cmets 提供的扩展答案 - 在理想情况下,我宁愿完全重写底层数据库!
  • 是的,重写编码不好的应用程序通常会更好,但遗憾的是,我们并不是在一个理想的世界,有时我们不得不忍受我们所拥有的,所以我理解你的情况。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多