为什么我的存储过程的datetime参数被拒绝了?

时间:2012-03-01 21:53:58

标签: java sql-server spring stored-procedures jdbc

我正在使用一个Java服务器应用程序,它使用Spring 3和C3P0访问Microsoft SQL Server 2008 R2数据库,使用的是Microsoft的JDBC 4驱动程序3.0版。

我有一个sproc,其输入定义如下:

@modifiedAfter datetime = NULL

我正在使用Spring构建对此sproc的调用。

我正在构建一个MapSqlParameterSource来包含我的参数:

MapSqlParameterSource in = new MapSqlParameterSource()
in.addValue("modifiedAfter", "2011-01-01T00:00:00", Types.TIMESTAMP)

但是当我执行电话时:

this.sprocCall.execute(in);

我明白了:

  

com.microsoft.sqlserver.jdbc.SQLServerException:从字符串转换日期和/或时间时转换失败

......我不明白为什么。

我尝试了一些添加参数的变体,例如将其作为Date传递,或者将其指定为VARCHAR,或者不指定类型 - 它们都不起作用。

我开始怀疑问题可能与Spring有关。我写了一个小的Groovy脚本来试图找出问题,这很好用:

dt = new DateTime("2012-02-01T00:00:00") // Joda DateTime
println sql.rows("exec spMySproc @modifiedAfter=${Sql.TIMESTAMP(dt.toString())}")

...但是当我尝试使用MapSqlParameterSource的等效方法时,我得到了上述错误。

此时,我很难过。

这是堆栈跟踪的顶部:

org.springframework.jdbc.BadSqlGrammarException: CallableStatementCallback; bad SQL grammar [{call spGetPoliciesCatalogPaged(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)}]; nested exception is com.microsoft.sqlserver.jdbc.SQLServerException: Conversion failed when converting date and/or time from character string.
    at org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.doTranslate(SQLStateSQLExceptionTranslator.java:97)
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80)
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80)
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:952)
    at org.springframework.jdbc.core.JdbcTemplate.call(JdbcTemplate.java:985)
    at org.springframework.jdbc.core.simple.AbstractJdbcCall.executeCallInternal(AbstractJdbcCall.java:368)
    at org.springframework.jdbc.core.simple.AbstractJdbcCall.doExecute(AbstractJdbcCall.java:342)
    at org.springframework.jdbc.core.simple.SimpleJdbcCall.execute(SimpleJdbcCall.java:164)

...其后是我的一些课程,然后是:

Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Conversion failed when converting date and/or time from character string.
    at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:197)
    at com.microsoft.sqlserver.jdbc.SQLServerResultSet$FetchBuffer.nextRow(SQLServerResultSet.java:4762)
    at com.microsoft.sqlserver.jdbc.SQLServerResultSet.fetchBufferNext(SQLServerResultSet.java:1682)
    at com.microsoft.sqlserver.jdbc.SQLServerResultSet.next(SQLServerResultSet.java:955)
    at com.mchange.v2.c3p0.impl.NewProxyResultSet.next(NewProxyResultSet.java:2859)
    at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:91)
    at org.springframework.jdbc.core.JdbcTemplate.processResultSet(JdbcTemplate.java:1124)
    at org.springframework.jdbc.core.JdbcTemplate.extractReturnedResults(JdbcTemplate.java:1023)
    at org.springframework.jdbc.core.JdbcTemplate$5.doInCallableStatement(JdbcTemplate.java:995)
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:936)
    ... 68 more

我尝试更新到最新版本的spring-jdbc,3.1.1,但它没有帮助。

我会感激任何帮助!

谢谢, 阿维

4 个答案:

答案 0 :(得分:2)

我的一位同事想出了这个。事实证明,我曾指责Spring和/或Microsoft SQL Server驱动程序。将字符串转换为日期/时间时问题确实是一个错误 - 但它不是我的参数直接问题,这是由我的sproc生成的动态SQL运行的查询的问题,< em> if 我传入了这个参数。

有问题的代码看起来像这样:

IF @modifiedAfter IS NOT NULL BEGIN
    SET @SQL = @SQL + N'AND mytable.ThingLastUpdated > @modifiedAfter'
END

@SQL中包含的动态SQL实际执行后,@modifiedAfter的内容 - 一个完全有效的DATETIME,从我的Java代码发送而没有任何问题 - 进行了比较使用mytable.ThingLastUpdated的内容 - 这是一个VARCHAR列,这意味着SQL Server必须将其内容转换为DATETIME,以便可以将它们与@modifiedAfter进行比较 - 但不是mytable.ThingLastUpdated中的所有值都可以成功转换,因此会抛出转换错误。

我决定修正的是将mytable.ThingLastUpdated的类型更改为DATETIME,并在插入时进行任何所需的转换,我认为这比在查询时这样做更有效。< / p>

获得的经验:如果SQL问题不在我的 Java代码中,它可能在我的 SQL中 - 而不是在Spring或JDBC驱动程序中。 PEBKAC。

答案 1 :(得分:1)

有一个类似的问题,正在寻找@ MSDN,看起来像Sql-Server 2005有一个精度转换的错误。据说你正在使用的版本提高了精度100ns。是否可以验证时间戳精度。以下是讨论的链接:Sql Server Conversion error

答案 2 :(得分:1)

如何将输入作为String / varchar传递,然后将其转换为sproc中的datetime?

答案 3 :(得分:1)

此错误肯定不是SQL问题,因为它将该字符串“2011-01-01T00:00:00”成功转换为datetime。您声明的sql参数类型是TIMESTAMP类型,并且您正在传递一个字符串。我认为这是它无法转换的地方。

尝试将sql参数类型声明为字符串或varchar而不是TimeStamp。