Разберем нестандартную ситуацию, с которой иногда сталкиваются системные администраторы при миграции баз данных. Предположим, вы перенесли регистр сведений из одной базы в другую прямым копированием таблиц средствами MS SQL Server. В самой СУБД поле даты выглядит корректно — 01.01.2016 0:00:00. Однако если открыть базу в режиме «1С:Предприятие», дата отображается как 01.01.0016 0:00:00 (теряется тысячелетие). Проанализируем причину такого поведения и рассмотрим способы решения проблемы.
Корень проблемы кроется в архитектурных особенностях взаимодействия платформы 1С и старых типов данных СУБД MS SQL Server. Исторически тип данных DATETIME в SQL Server поддерживает минимальную дату только с 1 января 1753 года. Поскольку в платформе 1С «пустой датой» считается 01.01.0001, СУБД выдавала бы ошибку переполнения при попытке ее записи напрямую.
Чтобы обойти это ограничение, платформа 1С использует механизм «Смещение дат 2000». Суть его работы заключается в следующем:
Ситуация с потерей тысячелетия возникает исключительно при прямом копировании таблиц между базами, у которых заданы разные настройки смещения (например, в базе-источнике смещение было «0», а в базе-приемнике — «2000»). SQL сервер копирует данные «как есть», перенося физическое значение 2016. Когда платформа 1С обращается к новой базе-приемнику, она видит физическое значение 2016 и, согласно своей настройке, вычитает из него 2000. В результате пользователь видит на экране 0016 год.
Важно отметить, что смещение дат (0 или 2000) задается строго один раз в момент добавления информационной базы в консоли администрирования серверов 1С. Штатными средствами платформы изменить это значение для уже существующей базы невозможно (настройка хранится в служебной таблице _YearOffset).
Если перенос таблиц прямыми запросами SQL критически необходим из-за гигантского объема данных (например, миллионы записей), самым безопасным решением будет удалить базу-приемник и создать ее заново в консоли кластера серверов 1С. При создании необходимо жестко указать параметр «Смещение дат: 0».
При таком сценарии данные из SQL-таблиц перенесутся корректно, так как платформа не будет применять механизм вычитания лет. Однако учитывайте, что нулевое смещение безопасно использовать только на современных версиях MS SQL Server, где платформа 1С работает с более новым типом данных DATETIME2, поддерживающим даты начиная с первого года нашей эры.
Если база-приемник уже создана со смещением 2000 и пересоздавать ее нельзя, правильным подходом будет отказаться от прямого копирования таблиц в СУБД. Программный интерфейс 1С абстрагирует разработчика от особенностей СУБД, поэтому проблема смещения полностью исключается при использовании стандартных инструментов:
Внимание: Прямое вмешательство в таблицы SQL является нарушением лицензионного соглашения 1С и может привести к нарушению логической целостности БД. Даты хранятся не только в таблицах движений, но и в итогах, а также участвуют в составных индексах. Применяйте этот метод только на свой страх и риск для тестовых или некритичных данных.
Если вы всё же решили исправить уже скопированные данные на уровне SQL, вам потребуется написать скрипт, который прибавит 2000 лет ко всем датам в целевой таблице регистра сведений. Рассмотрим логику такого запроса:
UPDATE [ИмяТаблицы]
SET [ИмяПоляДаты] = DATEADD(YEAR, 2000, [ИмяПоляДаты])
WHERE [ИмяПоляДаты] < '30000101'
В данном примере мы используем функцию SQL DATEADD для увеличения года. Условие ограничения (например, меньше 3000 года) необходимо, чтобы не увеличить значения тех дат, которые, возможно, уже были записаны корректно (с учетом прибавленных 2000 лет) или являются служебными «пустыми» датами с концом времен.
Подводя итог, настоятельно рекомендуем внимательно проверять параметры кластера серверов 1С на этапе создания новых информационных баз, чтобы избежать подобных коллизий при обслуживании СУБД.