Совместимость с типом данных собственного клиента SQL - несовместима с SQLOLEDB

Мы столкнулись с проблемой с нашим унаследованным приложением при переходе на использование собственного клиента SQL (SQLNCLI) в качестве поставщика ADO.

Наша оригинальная строка подключения была:

Provider=SQLOLEDB; Server=host; Database=bob; Integrated Security=SSPI;

мы изменили это на:

Provider=SQLNCLI11; Server=host; Database=bob; Integrated Security=SSPI; DataTypeCompatibility=80;

Мы обнаружили, что при вызове хранимой процедуры с использованием параметра adDBTimeStamp собственный клиент обрабатывает метку времени как маленькое время, а не как дату. Это вызывает у нас проблемы, так как мы используем 31 декабря 9999 года в качестве "верхней" даты в некоторых сравнениях, и собственный клиент завершается с ошибкой "Неверный формат даты", когда у SQLOLEDB не было проблем.

Теперь, похоже, мы можем просто сменить adDBTimeStamp на adDate в качестве типа данных при создании параметра, однако мне было интересно, не было ли чего-то, чего нам не хватало в строке соединения, прежде чем мы продолжим работу и внесем изменения в код.

Код VBScript для воспроизведения ниже. Во избежание сомнений, формат даты - Великобритания (дд / мм / гггг), прежде чем кто-то предложит нам использовать его 12/31/9999:-) Но также для подтверждения, CDate не подведет.

Set db = CreateObject("ADODB.Command")

' If Provider=SQLOLEDB then there is no error.
db.ActiveConnection = "Provider=SQLNCLI11; Server=host; Database=bob; Integrated Security=SSPI; DataTypeCompatibility=80;"
db.CommandText = "usp_FetchData"
db.CommandType = &H0004

' 135 is adDBTimeStamp
db.Parameters.Append db.CreateParameter("@screenDate", 135, 1, 20, CDate("31/12/9999"))

Set rs = CreateOBject("ADODB.RecordSet")
' Then this line fails with "Invalid date format" from SQLNCLI
rs.Open db

WScript.Echo rs.RecordCount

Обращение даты и времени назад к 2078 (в пределах диапазона дат smalldatetime) устраняет ошибку.

Как уже упоминалось, если можно найти исправление без изменения кода, это то, что мы бы предпочли, прежде чем мы перейдем к замене adDBTimeStamp на adDate. Я ожидал бы, что DataTypeCompatiblity=80 будет вести себя как SQLOLEDB; К сожалению, мой Google-фу не удался, когда выяснил, какое именно отображение типов использует SQLNCLI.

1 ответ

Решение, наконец, может быть найдено: через страницу MSDN Поддержка типов данных для улучшений даты и времени OLE DB есть следующий фрагмент к концу:

Отображение типов данных в ITableDefinition::CreateTable

Следующее сопоставление типов используется со структурами DBCOLUMNDESC, используемыми ITableDefinition::CreateTable:

[... таблица преобразований...]

Когда приложение указывает DBTYPE_DBTIMESTAMP в wType, оно может переопределить отображение на datetime2, указав имя типа в pwszTypeName. Если указано datetime, bScale должно быть 3. Если указано smalldatetime, bScale должно быть 0. Если bScale не соответствует wType и pwszTypeName, возвращается DB_E_BADSCALE.

При тестировании оказывается, что необходимо установить масштаб, применяемый к параметрам для SELECT и команд, а также для CreateTable. Поэтому, если мы изменим скрипт выше:

Set param = db.CreateParameter("@screenDate", 135, 1, 20, CDate("31/12/9999"))
param.NumericScale = 3
db.Parameters.Append param

... затем ошибка исчезает и хранимая процедура выполняется. Мы находимся на ранних этапах тестирования, однако приветствуем отзывы других, если это вызвало проблемы.

Другие вопросы по тегам