我正在使用一个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,但它没有帮助。
我会感激任何帮助!
谢谢, 阿维
答案 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。