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

Мы столкнулись с проблемой в нашем устаревшем приложении при переходе на использование SQL Native Client (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 для воспроизведения ниже. Во избежание сомнений, формат даты - британский (дд/мм/гггг), прежде чем кто-то предложит использовать 31.12.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. Я ожидал, что DataTypeCompatibility=80 будет вести себя как SQLOLEDB; К сожалению, мой Google-fu не удалось выяснить, какое именно сопоставление типов использует SQLNCLI.


person Chris J    schedule 10.09.2015    source источник


Ответы (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

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

person Chris J    schedule 27.02.2017