2012-03-01 82 views
3

我正在使用Spring 3和C3P0訪問Microsoft SQL Server 2008 R2數據庫,使用Microsoft的JDBC 4驅動程序版本3.0的Java服務器應用程序。爲什麼我的datetime參數存儲過程被拒絕?

我有一個具有像這樣定義的輸入一個存儲過程:

@modifiedAfter datetime = NULL 

我使用Spring來構建這個存儲過程的調用。

我構建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,但它沒有幫助。

我會很感激任何幫助!

感謝, 阿維

+2

你試過字符串而不是Types.TIMESTAMP嗎?我認爲Types.TIMESTAMP格式不能在sql server中轉換。 – 2012-03-01 21:59:05

+1

SQL Server中的TIMESTAMP與日期或時間完全無關。 – 2012-03-01 22:21:08

+0

@ThitLwinOo,@Aaron:我沒有使用SQL Server'timestamp'格式。我正在使用JDBC TIMESTAMP格式。根據[本頁](http://msdn.microsoft.com/zh-cn/library/ms378878.aspx),JDBC驅動程序將JDBC TIMESTAMP格式映射到SQL Server類型「datetime」和「datetime2」。另外,使用JDBC TIMESTAMP的上述Groovy腳本工作得很好。 – 2012-03-01 22:41:45

回答

2

我的一位同事明白了這一點。事實證明,我通過指責Spring和/或Microsoft SQL Server驅動程序而跳槽。在將字符串轉換爲日期/時間時,問題確實是錯誤的 - 但直接與我的參數不成問題,這是由我的存儲庫生成的動態SQL運行的查詢的問題,如果我傳入了這個參數。

有問題的代碼看起來是這樣的:

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,並在插入時進行任何所需的轉換,我認爲在查詢時這樣做會更有效。

教訓:如果一個SQL問題並不在 Java代碼,它可能在 SQL - 不是在春季或JDBC驅動程序。 PEBKAC。

1

曾在一個類似的問題,並期待@ MSDN和看起來像SQL-Server 2005中曾與精度轉換的bug。據說你使用的版本已經提高了100ns的精度。是否有可能驗證時間戳的精度。這裏是鏈接的討論:Sql Server Conversion error

+0

我有問題的示例代碼的值是硬編碼的:'in.addValue(「modifiedAfter」,「2011-01-01T00:00:00」,Types.TIMESTAMP)''所以你可以看到沒有精度級別的數據一個標準的SQL Server DateTime將無法表示。 – 2012-03-01 22:44:20

+0

in.addValue(「modifiedAfter」,「2011-01-01T00:00:00」,Types.String),那個怎麼樣?因爲值「2011-01-01T00:00:00」是沒有問題要在SQL Server中進行轉換。 – 2012-03-02 00:18:27

+0

@ThitLwinOo'Types.String'不存在。你可以看到所有JDBC類型的列表[here](http://docs.oracle.com/javase/7/docs/api/java/sql/Types.html)。我嘗試過'Types.VARCHAR',我得到了同樣的錯誤。 – 2012-03-02 16:24:34

1

如何使輸入字符串作爲/ VARCHAR,然後在存儲過程將其轉換爲datetime?

+2

儘管我認爲這可能是一種可用的解決方法,但我很感謝幫助,解決方法並非我正在尋找的 - 我想了解爲什麼我的代碼(應該是_should_工作)無法正常工作。 – 2012-03-05 16:37:21

1

此錯誤是defenitely不是SQL問題bacause它是字符串轉換 「2011-01-01T00:00:00」 爲datetime成功。你聲明的SQL參數類型是TIMESTAMP類型,並且你正在傳遞一個字符串。我認爲那是它未能轉換的地方。

嘗試聲明sql參數類型爲字符串或varchar而不是TimeStamp。

+0

正如我在我的問題中提到的,我已經嘗試過了。它不起作用。 – 2012-03-05 16:35:48

+0

您是否嘗試過提供其他日期格式? – Virus 2012-03-05 16:39:36

+0

您的意思是價值還是指定的類型?爲了清楚起見,我很確定這裏的問題與Spring有關 - 我非常清楚,我試圖做的語義應該由JDBC和MSSQL支持。無論如何,我已經嘗試過各種各樣的值和指定類型的組合--Java'Date'對象,'Types.VARCHAR'等。在這一點上,我相信Spring正在反思這個存儲過程,看到參數被聲明爲'DATETIME',並試圖將價值強加給某種兼容的東西 - 並因爲某種原因失敗。我想我將不得不挖掘Spring的源代碼... – 2012-03-05 16:58:29

相關問題