Почему даты превращаются в пустые значения во временных таблицах запросов 1С при работе с MS SQL Server 2016?

Системный администратор 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При переводе информационных баз 1С:Предприятие на MS SQL Server 2016 можно столкнуться с неожиданным поведением системы: документы перестают проводиться, возникают ошибки при записи в регистры, а данные типа Дата во временных таблицах запросов внезапно становятся равными пустой дате (01.01.0001 0:00:00).

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

Симптомы и проявление проблемы

Проблема проявляется при попытке поместить данные типа Дата во временную таблицу в языке запросов 1С. При этом способ передачи даты значения не имеет — ошибка воспроизводится как при передаче таблицы значений, так и при использовании одиночных параметров или выборке из существующих документов базы данных.

Проанализируем базовый пример передачи таблицы значений в запрос:


Таблица = Новый ТаблицаЗначений;
Таблица.Колонки.Добавить("Дата", Новый ОписаниеТипов("Дата"));

НоваяСтрока = Таблица.Добавить();
НоваяСтрока.Дата = Дата(2006, 1, 1);

Запрос = Новый Запрос;
Запрос.Текст = 
"ВЫБРАТЬ
|   ВТ.Дата
|ПОМЕСТИТЬ ВТ
|ИЗ
|   &ВТ КАК ВТ
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
|   ВТ.Дата
|ИЗ
|   ВТ КАК ВТ";

Запрос.УстановитьПараметр("ВТ", Таблица);
ТаблицаЗапроса = Запрос.Выполнить().Выгрузить();

В нормальном режиме результат содержит переданную дату 01.01.2006. Однако в рассматриваемой ситуации в итоговую выборку попадает пустая дата.

Разберем еще один случай — передача даты через параметр запроса &Дата:


Запрос = Новый Запрос;
Запрос.Текст = 
"ВЫБРАТЬ
|   &Дата КАК Дата
|ПОМЕСТИТЬ ВТ
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
|   ВТ.Дата
|ИЗ
|   ВТ КАК ВТ";

Запрос.УстановитьПараметр("Дата", ТекущаяДата());

Выборка = Запрос.Выполнить().Выбрать();

Если Выборка.Следующий() Тогда
    Сообщить(Выборка.Дата); // Выводит пустую дату 01.01.0001 0:00:00
КонецЕсли;

Даже если дата выбирается напрямую из физической таблицы СУБД (например, из документа Документ.БольничныйЛист) и помещается во временную таблицу ПОМЕСТИТЬ ВТ, при последующем чтении из этой временной таблицы значение поля Дата теряется:


Запрос = Новый Запрос;
Запрос.Текст = 
"ВЫБРАТЬ ПЕРВЫЕ 1
|   БольничныйЛист.Дата
|ПОМЕСТИТЬ ВТ
|ИЗ
|   Документ.БольничныйЛист КАК БольничныйЛист
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
|   ВТ.Дата
|ИЗ
|   ВТ КАК ВТ";

РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();

Если Выборка.Следующий() Тогда
    Сообщить(Выборка.Дата); // На выходе — пустая дата
КонецЕсли;

Причина возникновения ошибки

Выясним, почему СУБД сбрасывает значения. Причина кроется в несовместимости версий провайдеров доступа к данным (драйверов СУБД), установленных на сервере приложений 1С:Предприятие.

Если на сервере 1С установлена устаревшая версия библиотеки Microsoft SQL Server Native Client (например, для SQL Server 2005 или 2008), то при взаимодействии с MS SQL Server 2016 протокол передачи данных некорректно сопоставляет типы данных при создании временных таблиц в базе TempDB. Типы данных DATETIME и DATETIME2 при маршалинге параметров во временную таблицу теряют значения, превращаясь в нули.

Часто эта проблема возникает в инфраструктурах, где один и тот же рабочий сервер 1С обслуживает базы, расположенные на разных экземплярах SQL Server (например, старом MS SQL 2005 и новом MS SQL 2016), либо в многосерверных кластерах 1С, где компоненты Native Client установлены несинхронно.

Способы решения и настройки СУБД

  1. Обновление Microsoft SQL Server Native Client / OLE DB Driver на сервере 1С:

    Необходимо установить на рабочий сервер 1С актуальную версию компонента подключения к SQL Server. Для MS SQL Server 2016 требуется использовать Microsoft SQL Server 2012 Native Client (пакет sqlncli11.msi) или более современный Microsoft OLE DB Driver for SQL Server (MSOLEDBSQL).

  2. Проверка всех узлов кластера 1С:Предприятие:

    Если кластер состоит из нескольких серверов, актуальный драйвер СУБД должен быть установлен на каждом рабочем сервере. Иначе при перераспределении сеансов или рабочих процессов проблема будет возникать периодически.

  3. Проверка прав пользователя SQL:

    Убедимся, что учетная запись, под которой сервер 1С подключается к MS SQL Server, имеет корректные права в СУБД (роль db_owner для целевой базы данных и разрешения на создание временных таблиц в TempDB).

  4. Обновление платформы 1С:Предприятие:

    При использовании старых релизов платформы (например, 8.3.10 и ниже) рекомендуется обновить платформу 1С до актуальных релизов 8.3, в которых доработаны механизмы взаимодействия с MS SQL Server 2016 и выше.

После установки соответствующего Native Client и перезапуска службы кластера 1С:Предприятие передача дат во временные таблицы запросов начнет работать корректно, без потери значений.

← На главную