什么可能导致 SQL Server JDBC 错误“未为参数号 0 设置值”以访问输出参数?

Posted

技术标签:

【中文标题】什么可能导致 SQL Server JDBC 错误“未为参数号 0 设置值”以访问输出参数?【英文标题】:What can cause the SQL Server JDBC error 'The value is not set for the parameter number 0' for an output parameter access? 【发布时间】:2009-05-13 15:25:03 【问题描述】:

我有一些访问 SQL Server 2005 的 Java 代码,看起来像这样:

CallableStatement cstmt = ...;
... // Set input parameters
cstmt.registerOutParameter(11, Types.INTEGER);
cstmt.execute();
int out = cstmt.getInt(11);

并且从最后一行抛出以下异常:

com.microsoft.sqlserver.jdbc.SQLServerException: The value is not set 
     for the parameter number 0.
   at com.microsoft.sqlserver.jdbc.SQLServerException.
     makeFromDriverError(Unknown Source)
   at com.microsoft.sqlserver.jdbc.SQLServerCallableStatement.
     skipOutParameters(Unknown Source)
   at com.microsoft.sqlserver.jdbc.SQLServerCallableStatement.
     getOutParameter(Unknown Source)
   at com.microsoft.sqlserver.jdbc.SQLServerCallableStatement.
     getterGetParam(Unknown Source)
   at com.microsoft.sqlserver.jdbc.SQLServerCallableStatement.
     getInt(Unknown Source)
   at org.jboss.resource.adapter.jdbc.WrappedCallableStatement.
     getInt(WrappedCallableStatement.java:192)

被调用的存储过程如下所示:

CREATE PROCEDURE dbo.stored_proc ( -- 10 input parameters
                                 , @out_param INT OUTPUT) AS

-- Variable declarations 

SET @out_param = 0

-- Do processing...

SET @out_param = 1

既然在进入存储过程时输出参数设置为零,在什么情况下可以不设置该值?还是我误解了错误消息?

此错误可通过以下方式重现:

SQL Server JDBC 驱动程序 1.2 SQL Server 2005(64 位)服务包 2 SQL Server 2005(64 位)服务包 3

更新:它似乎是由于存储过程的-- Do processing... 部分而发生的。删除它可以消除错误。这里要重现的代码太多,我想要一些指向可能原因的指针,以缩小可能的候选范围。

更新:将错误(例如除以零)注入存储过程的-- Do processing... 部分不会导致抛出此异常(相反,正如预期的那样,execute() 调用失败并显示相应的错误消息)。

更新:反编译 com.microsoft.sqlserver.jdbc.SQLServerCallableStatement 类表明“参数号 0”是存储过程返回值

更新:我无法通过直接通过 Management Studio 调用存储过程来重现此问题。

更新:这个错误的最终原因似乎是存储过程中的死锁。但是,通常死锁会导致 execute() 调用失败,并出现 SQLException 包装 SQL Server 错误代码 1205...

【问题讨论】:

【参考方案1】:

在您的参数上,您只是声明它们还是将它们设置为默认值?尝试将它们设置为默认值 null 或其他值,看看是否仍然出现错误。

如果你有一个参数没有设置为默认值并且你在执行存储过程时没有向它传递值,那么sql server 不喜欢它。

【讨论】:

OUTPUT 参数也是这样吗? 没有任何线索。我不完全确定我理解你所说的输出参数是什么意思 除非我遗漏了什么,“没有为参数编号 0 设置值。”,很可能是指尚未设置的输入参数? @Jonn Sansom - 错误消息令人困惑,我最初的假设是它引用了输入参数。但是,引发异常的应用程序代码的行号(上面的堆栈跟踪中未显示)是 getInt() 输出参数访问调用。 @Thirster42 - 在这种情况下,输出参数是由存储过程而不是 Java 代码设置的参数(即那些在 Java 代码中使用 registerOutParameter() 注册并在存储过程声明中定义为 OUTPUT 的参数) .【参考方案2】:

您是否正在注册输出参数?根据docs“在执行存储过程之前必须注册所有的OUT参数。”

【讨论】:

【参考方案3】:

我想到了几件事:

    您没有返回 x(其中 x 是表示处理结果的 INT,0 = 成功,其他任何值都表示警告或错误)。 除了输出参数之外,您的客户端代码没有为返回值分配参数。

希望这会有所帮助,

比尔

【讨论】:

【参考方案4】:

反编译 com.microsoft.sqlserver.jdbc.SQLServerCallableStatement 类建议 'parameter number 0' 是存储过程的返回值。

没错。如果您的存储过程定义有 11 个输入/输出参数,您实际上需要在调用代码中定义 12 个。参数0为返回码。

例如,对于具有一个输入和一个输出参数的 SP,在 SSMS 中运行以下命令:

DECLARE @ReturnValue INT
DECLARE @P1 INT, @P2 INT

EXEC @ReturnValue= YourSP(@P1,@P2 OUTPUT)

这里实际上需要处理三个参数,而不是两个。

【讨论】:

【参考方案5】:

如果有人在 SQL Server 2008 上仍然遇到此问题。

在尝试为 DateTime 字段设置时间戳时,我在更新语句中遇到了同样的问题。违规字段位于与报告的索引不同的索引处的 where 子句中。

【讨论】:

以上是关于什么可能导致 SQL Server JDBC 错误“未为参数号 0 设置值”以访问输出参数?的主要内容,如果未能解决你的问题,请参考以下文章

Java Spring jdbc sql server连接错误

什么类型的错误导致 MS SQL Server 中的 XACT_STATE 为 1?

Sql Server JDBC 驱动程序错误

连接到 sql server 时出现 pyspark jdbc 错误

在SQL Server 2005中附加.mdf文件错误

Glassfish“连接已关闭”错误与连接池、JDBC 和 SQL Server 2008