Почему мой параметр datetime для хранимой процедуры отклоняется? - PullRequest
3 голосов
/ 02 марта 2012

Я работаю над приложением на сервере Java, которое использует Spring 3 и C3P0 для доступа к базе данных Microsoft SQL Server 2008 R2, используя версию 3.0 драйвера JDBC 4 от Microsoft.

У меня есть 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 ]

2 голосов
/ 06 марта 2012

Мой коллега понял это.Оказывается, я бросил вызов, обвиняя Spring и / или драйвер Microsoft SQL Server.Проблема была действительно в ошибке при преобразовании символьной строки в дату / время - но это не было проблемой непосредственно с моим параметром, это была проблема с запросом, который выполнялся динамическим SQL, сгенерированным моим sproc, , если Я передал этот параметр.

Проблемный код выглядит примерно так:

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 - не в Spring или драйвере JDBC.PEBKAC.

1 голос
/ 05 марта 2012

Как насчет передачи ввода в виде String / varchar и последующего преобразования его в datetime в sproc?

1 голос
/ 05 марта 2012

Эта ошибка определенно не является проблемой SQL, потому что она успешно преобразует эту строку «2011-01-01T00: 00: 00» в datetime. Объявленный вами тип параметра sql имеет тип TIMESTAMP, и вы передаете строку. Я думаю, что именно там он не может быть преобразован.

Попробуйте объявить тип параметра sql как строку или varchar вместо TimeStamp.

1 голос
/ 02 марта 2012

Была похожая проблема, она искала @ MSDN и, похоже, в Sql-Server 2005 была ошибка с прецизионным преобразованием.Возможно, версия, которую вы используете, увеличила точность 100 нс.Удастся ли проверить точность отметки времени.Вот ссылка для обсуждения: Ошибка преобразования сервера Sql

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...