Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

### Ошибки в SQL Server при передаче даты '12/30/1899': проблемы и решения через ADO и DataTypeCompatibility

Delphi , Технологии , OLE

Ошибки в SQL Server при передаче даты '12/30/1899': проблемы и решения через ADO и DataTypeCompatibility

При работе с базой данных SQL Server через ActiveX Data Objects (ADO) и использовании параметризованных запросов может возникнуть проблема с передачей даты '12/30/1899'. Эта дата имеет особое значение в OLE Automation и в частности в структуре VARIANT, используемой в ADO. В некоторых случаях, при использовании драйверов SQL Server Native Client (SQLNCLI) и включенном режиме DataTypeCompatibility, может возникать ошибка "Недопустимый формат даты".

Проблема

При попытке использовать параметризованный запрос с datetime значением '12/30/1899' через ADO и драйверы SQL Server Native Client, в режиме DataTypeCompatibility, возникает исключение с сообщением "Недопустимый формат даты". Это происходит до того, как запрос достигает SQL Server, и связано с самой реализацией драйверов.

Решение

Для решения этой проблемы необходимо изменить способ передачи параметра даты. Вместо использования типа adDBTimeStamp, следует установить свойство NumericScale параметра в диапазоне 1-7, что позволит драйверу интерпретировать параметр как datetime2, а не smalldatetime.

Parameter p = cmd.CreateParameter("", adDBTimeStamp, adParamInput, 0, v);
p.NumericScale = 1; // или любое другое значение от 1 до 7

Такой подход позволяет избежать ошибки и успешно выполнить параметризованный запрос.

Альтернативное решение

В качестве альтернативы, можно использовать передачу datetime значений в виде строк в формате ODBC 24-часового времени, например adVarChar с использованием формата yyyy-mm-dd hh:mm:ss.zzz.

Пример кода на Object Pascal (Delphi)

program ParameterizedQuery;
{$APPTYPE CONSOLE}
uses
  System.SysUtils,
  ComObj,
  ActiveX,
  ADOdb,
  ADOint,
  Variants;

function GetConnection(ProviderName: string; DataTypeCompatibility: Boolean): _Connection;
var
  connectionString: string;
begin
  connectionString := 'Provider=' + ProviderName + ';Data Source=...;';
  if DataTypeCompatibility then
    connectionString := connectionString + 'DataTypeCompatibility=80;';
  Result := CoConnection.Create;
  Result.Open(connectionString, '', '', adConnectUnspecified);
end;

procedure TestDateParameter(ProviderName: string; DataTypeCompatibility: Boolean);
var
  dt: TDateTime;
  v: OleVariant;
  cmd: _Command;
  cn: _Connection;
  recordsAffected: OleVariant;
begin
  dt := EncodeDate(1899, 12, 30); // 12/30/1899 12:00:00 AM (нулевая дата в Delphi)
  v := dt; // Тип variants - VT_DATE (7)

  cmd := CoCommand.Create;
  cmd.CommandText := 'SELECT ? AS SomeDate';
  with cmd.CreateParameter('', adDBTimeStamp, adParamInput, 0, 0) do
  begin
    SetDataType(adDBTimeStamp);
    SetNumericScale(1); // Установка свойства NumericScale
    cmd.Parameters.Append(Self);
  end;
  cmd.Parameters[0].PutValue(v);

  try
    cn := GetConnection(ProviderName, DataTypeCompatibility);
  except
    on E: Exception do
    begin
      Writeln('Provider ' + ProviderName + ' не установлен: ' + E.Message);
      Exit;
    end;
  end;

  cmd.Set_ActiveConnection(cn);
  try
    cmd.Execute({out}recordsAffected, EmptyParam, adExecuteNoRecords);
    Writeln('Provider ' + ProviderName + ' (DataTypeCompatibility=' + (DataTypeCompatibility: 'with': 'without') + '): success.');
  except
    on E: Exception do
    begin
      Writeln('Provider ' + ProviderName + ' (DataTypeCompatibility=' + (DataTypeCompatibility: 'with': 'without') + ') failed: ' + E.Message);
    end;
  end;
end;

begin
  CoInitialize(nil);
  TestDateParameter('SQLOLEDB', False);
  TestDateParameter('SQLNCLI11', False);
  TestDateParameter('SQLNCLI11', True);
  // ... аналогично для других доступных драйверов
end.

Заключение

При работе с SQL Server через ADO и параметризованные запросы важно учитывать особенности работы с датами, особенно при использовании режима DataTypeCompatibility и драйверов SQL Server Native Client. Установка свойства NumericScale для параметра типа adDBTimeStamp позволяет избежать ошибок при передаче даты '12/30/1899'.

Создано по материалам из источника по ссылке.

Проблема и решения связаны с особенностями передачи даты '12/30/1899' в SQL Server через ADO и настройками режима DataTypeCompatibility.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: OLE ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2024-12-26 16:25:29/0.0033938884735107/0