Почему при переносе таблиц 1С в SQL теряется тысячелетие в датах и как это исправить?

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

Разберем нестандартную ситуацию, с которой иногда сталкиваются системные администраторы при миграции баз данных. Предположим, вы перенесли регистр сведений из одной базы в другую прямым копированием таблиц средствами MS SQL Server. В самой СУБД поле даты выглядит корректно — 01.01.2016 0:00:00. Однако если открыть базу в режиме «1С:Предприятие», дата отображается как 01.01.0016 0:00:00 (теряется тысячелетие). Проанализируем причину такого поведения и рассмотрим способы решения проблемы.

Выясним причину: Смещение дат в 1С и MS SQL

Корень проблемы кроется в архитектурных особенностях взаимодействия платформы 1С и старых типов данных СУБД MS SQL Server. Исторически тип данных DATETIME в SQL Server поддерживает минимальную дату только с 1 января 1753 года. Поскольку в платформе 1С «пустой датой» считается 01.01.0001, СУБД выдавала бы ошибку переполнения при попытке ее записи напрямую.

Чтобы обойти это ограничение, платформа 1С использует механизм «Смещение дат 2000». Суть его работы заключается в следующем:

  1. При записи данных в базу SQL платформа прибавляет ко всем датам 2000 лет. Таким образом, пустая дата физически сохраняется в таблице как 01.01.2001.
  2. При чтении данных из базы платформа автоматически отнимает эти 2000 лет, возвращая пользователю исходное значение.

Ситуация с потерей тысячелетия возникает исключительно при прямом копировании таблиц между базами, у которых заданы разные настройки смещения (например, в базе-источнике смещение было «0», а в базе-приемнике — «2000»). SQL сервер копирует данные «как есть», перенося физическое значение 2016. Когда платформа 1С обращается к новой базе-приемнику, она видит физическое значение 2016 и, согласно своей настройке, вычитает из него 2000. В результате пользователь видит на экране 0016 год.

Важно отметить, что смещение дат (0 или 2000) задается строго один раз в момент добавления информационной базы в консоли администрирования серверов 1С. Штатными средствами платформы изменить это значение для уже существующей базы невозможно (настройка хранится в служебной таблице _YearOffset).

Способ 1: Пересоздание базы-приемника без смещения

Если перенос таблиц прямыми запросами SQL критически необходим из-за гигантского объема данных (например, миллионы записей), самым безопасным решением будет удалить базу-приемник и создать ее заново в консоли кластера серверов 1С. При создании необходимо жестко указать параметр «Смещение дат: 0».

При таком сценарии данные из SQL-таблиц перенесутся корректно, так как платформа не будет применять механизм вычитания лет. Однако учитывайте, что нулевое смещение безопасно использовать только на современных версиях MS SQL Server, где платформа 1С работает с более новым типом данных DATETIME2, поддерживающим даты начиная с первого года нашей эры.

Способ 2: Использование штатных механизмов обмена

Если база-приемник уже создана со смещением 2000 и пересоздавать ее нельзя, правильным подходом будет отказаться от прямого копирования таблиц в СУБД. Программный интерфейс 1С абстрагирует разработчика от особенностей СУБД, поэтому проблема смещения полностью исключается при использовании стандартных инструментов:

  1. Выгрузка и загрузка через .dt: Если создать пустую базу со смещением 2000 и перенести данные из источника через конфигуратор в формате файла выгрузки, платформа на лету обработает все даты и корректно прибавит к ним необходимое смещение при записи в SQL.
  2. Перенос через XML: Использование обработки «Универсальный обмен данными». Хотя на больших объемах (от нескольких миллионов строк) это может занять много времени, данные перенесутся без искажений.
  3. Обмен через COM-соединение: Позволяет программно читать данные из базы-источника и записывать в базу-приемник. Даты будут конвертироваться платформой автоматически.

Способ 3: Корректировка дат прямым запросом (Update)

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

Если вы всё же решили исправить уже скопированные данные на уровне SQL, вам потребуется написать скрипт, который прибавит 2000 лет ко всем датам в целевой таблице регистра сведений. Рассмотрим логику такого запроса:


UPDATE [ИмяТаблицы] 
SET [ИмяПоляДаты] = DATEADD(YEAR, 2000, [ИмяПоляДаты]) 
WHERE [ИмяПоляДаты] < '30000101'

В данном примере мы используем функцию SQL DATEADD для увеличения года. Условие ограничения (например, меньше 3000 года) необходимо, чтобы не увеличить значения тех дат, которые, возможно, уже были записаны корректно (с учетом прибавленных 2000 лет) или являются служебными «пустыми» датами с концом времен.

Подводя итог, настоятельно рекомендуем внимательно проверять параметры кластера серверов 1С на этапе создания новых информационных баз, чтобы избежать подобных коллизий при обслуживании СУБД.

← На главную