При работе с программными продуктами 1С на платформе 8.3, особенно при переносе данных в конфигурацию 1С:Зарплата и Управление Персоналом 3 (ЗУП), специалисты часто сталкиваются с критической ошибкой выполнения запроса. Текст ошибки обычно выглядит так: «Ошибка в значении типа 'Дата'. Дата '31.12.0001 0:00:00' не может быть записана в базу данных на MS SQL Server с нулевым смещением дат», что иногда случается при переносе данных из КА 2.5 в ЗУП 3.1. В этой статье мы подробно разберем, почему возникает эта ситуация, как работают механизмы хранения дат в СУБД и какими способами можно устранить проблему. При необходимости можно использовать готовую обработку для переноса данных из КА 2.5 в ЗУП 3.1.
Для начала выясним причину, по которой MS SQL Server отказывается принимать дату начала нашей эры. Основная техническая сложность заключается в типе данных DATETIME, который платформа 1С:Предприятие исторически использует для хранения календарных значений в таблицах SQL. У этого типа данных есть жесткое ограничение: минимально возможная дата — 1 января 1753 года.
Такое странное на первый взгляд ограничение имеет исторические корни. Переход с юлианского на григорианский календарь в Британии и её колониях произошел в 1752 году. Чтобы избежать путаницы и сложных алгоритмических расчетов при пересчете дат в период календарной реформы, разработчики SQL Server на ранних этапах развития продукта решили ограничить нижний порог даты 1753 годом. Несмотря на то, что в современных версиях SQL Server существует тип DATETIME2, поддерживающий даты с 0001 года, платформа 1С продолжает использовать стандартный DATETIME для обеспечения совместимости и стабильности работы механизмов СУБД.
В системе 1С:Предприятие «пустая» дата представлена как 01.01.0001 0:00:00. Если база данных создана с параметром «Смещение дат = 0», платформа пытается записать эту дату «как есть». SQL Server блокирует эту операцию, что и приводит к аварийному завершению работы или ошибке запроса.
Для решения этой фундаментальной несовместимости разработчики платформы 1С предусмотрели специальный механизм — смещение дат. Рассмотрим, как он работает:
01.01.0001 превращается в 01.01.2001, что абсолютно легитимно для SQL Server. При чтении данных платформа производит обратную операцию, вычитая 2000 лет, поэтому пользователь в интерфейсе 1С видит корректные данные.Важный нюанс: выбор смещения возможен только в момент создания информационной базы на сервере 1С. Изменить этот параметр в настройках уже существующей базы невозможно.
Если вы столкнулись с ошибкой при переносе данных или в типовых механизмах ЗУП, наиболее надежным способом будет приведение параметров базы данных к рекомендованным стандартам (использование смещения 2000). Чтобы снизить риск возникновения подобных ошибок на этапе настройки новой базы, можно посетить раздел решений для переноса данных в ЗУП и подобрать оптимальный алгоритм миграции. Пройдем по шагам этот процесс:
1. Выполните выгрузку текущей информационной базы в файл резервной копии (формат .dt), что является стандартным шагом переноса данных в чистую ЗУП 3.1. Это необходимо сделать через Конфигуратор: Администрирование — Выгрузить информационную базу.
2. Удалите регистрацию информационной базы в консоли администрирования серверов 1С (при этом саму базу в SQL можно не удалять, если вы планируете создать новую с другим именем).
3. Создайте новую информационную базу на сервере 1С. В диалоговом окне создания базы обратите внимание на поле «Смещение дат». Установите там значение 2000.
4. После создания пустой базы зайдите в неё через Конфигуратор и выполните загрузку ранее созданного файла: Администрирование — Загрузить информационную базу.
После этой процедуры проблема с записью дат начала эры исчезнет навсегда. Однако помните, что если вы пишете прямые SQL-запросы к таблицам базы (например, для BI-систем), вам придется вручную вычитать 2000 лет из значений колонок с датами.
Бывают ситуации, когда пересоздать базу невозможно или ошибка возникает в конкретном самописном запросе. Рассмотрим пример кода, который вызывает проблему:
ВЫБРАТЬ
ВЫБОР КОГДА Регистр.СоставнаяЧасть В (&СоставнаяЧастьГодовыеПремии)
ТОГДА ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(1, 12, 31), ГОД, Регистр.Год - 1)
ИНАЧЕ Регистр.Период
КОНЕЦ КАК Период
ИЗ РегистрНакопления.ДанныеОНачисленияхДляРасчетаСреднегоЗаработкаОбщий КАК Регистр
Проанализируем ситуацию: здесь используется функция ДОБАВИТЬКДАТЕ, где базой выступает ДАТАВРЕМЯ(1, 12, 31). Если поле Регистр.Год окажется незаполненным (равным нулю) или некорректным, результат вычисления может уйти в диапазон дат до 1753 года. SQL Server не может обработать результат такой арифметической операции «на лету» в запросе.
Чтобы избежать ошибки без пересоздания базы, мы можем изменить логику формирования даты. Вместо манипуляций с первым годом нашей эры, попробуем использовать заведомо корректную «минимальную» дату, например, из 20-го или 21-го века, либо добавить проверку. Рассмотрим исправленный вариант запроса:
ВЫБРАТЬ
ВЫБОР
КОГДА Регистр.СоставнаяЧасть В (&СоставнаяЧастьГодовыеПремии) И Регистр.Год > 1
ТОГДА ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(1900, 12, 31), ГОД, Регистр.Год - 1900)
КОГДА Регистр.СоставнаяЧасть В (&СоставнаяЧастьГодовыеПремии)
ТОГДА ДАТАВРЕМЯ(1900, 1, 1)
ИНАЧЕ Регистр.Период
КОНЕЦ КАК Период
ИЗ РегистрНакопления.ДанныеОНачисленияхДляРасчетаСреднегоЗаработкаОбщий КАК Регистр
В данном примере мы заменили рискованную дату 0001 год на 1900 год. Эта дата гарантированно поддерживается SQL Server даже при нулевом смещении. Также хорошей практикой является использование NULL вместо пустых дат в сложных расчетах, если бизнес-логика это позволяет. Для анализа и отладки алгоритмов расчета среднего заработка можно использовать консоль запросов для ЗУП с поддержкой методов программного интерфейса.
Выясним, почему эта проблема часто всплывает именно в ЗУП 3. При переносе данных из старых редакций (например, ЗУП 2.5) система анализирует периоды стажа и начислений. В некоторых случаях данные переносятся с незаполненными периодами, которые 1С интерпретирует как 01.01.0001. Если в алгоритме расчета среднего заработка или пересчета премий встречается жестко зашитая логика обращения к началу эры (как в сообщении автора темы), запрос «падает».
Специалисты рекомендуют:
Год в регистрах начислений.ДАТАВРЕМЯ(1, 12, 31) на более позднюю дату.Таким образом, мы выяснили, что корень проблемы лежит в архитектурном ограничении MS SQL Server. Наилучшим стратегическим решением является использование базы данных со смещением дат 2000. Если же вы ограничены текущей инфраструктурой, используйте в запросах проверку условий и замену минимальных дат на технологический минимум (например, 01.01.1900), чтобы обеспечить стабильную работу системы.