При настройке обменов данными в 1С с использованием планов обмена часто возникает ситуация, когда в таблице регистрации изменений скапливается так называемый «мусор». Это записи о том, что объект был изменен, но самого объекта (записи регистра сведений) в базе уже физически не существует. Разберем по шагам, как выявить такие записи и безопасно их удалить, не затрагивая при этом нормальные, актуальные изменения, ожидающие отправки.
Для начала проанализируем ситуацию и выясним причину появления мусора. Данные в таблице Изменения остаются, если запись регистра была удалена, но регистрация для узла не была очищена. Чтобы найти такие записи, воспользуемся запросом. Нам необходимо выполнить левое соединение виртуальной таблицы изменений с основной таблицей регистра и отфильтровать те строки, где в основной таблице результат равен NULL.
Посмотрим на пример запроса для независимого непериодического регистра сведений с одним измерением ОсновноеСредство:
ВЫБРАТЬ РАЗЛИЧНЫЕ
ТаблицаИзменений.ОсновноеСредство КАК ОсновноеСредство,
ТаблицаИзменений.Узел КАК Узел
ИЗ
РегистрСведений.ПервоначальныеСведения.Изменения КАК ТаблицаИзменений
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ПервоначальныеСведения КАК ОсновнаяТаблица
ПО ТаблицаИзменений.ОсновноеСредство = ОсновнаяТаблица.ОсновноеСредство
ГДЕ
ОсновнаяТаблица.ОсновноеСредство ЕСТЬ NULL
Этот запрос вернет нам список узлов и измерений, для которых записи в основной таблице отсутствуют.
Рассмотрим первый способ удаления найденного мусора. Для этого нам потребуется объект НаборЗаписей и платформенный метод ПланыОбмена.УдалитьРегистрациюИзменений(). Главное правило: в отбор набора записей необходимо передать абсолютно все измерения, которые входят в ключ регистра. Если регистр периодический, в отбор также обязательно нужно добавить поле Период.
Проанализируем пример кода, который перебирает результат предыдущего запроса и удаляет регистрации:
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
НаборЗаписей = РегистрыСведений.ПервоначальныеСведения.СоздатьНаборЗаписей();
// Устанавливаем отбор по всем измерениям регистра
НаборЗаписей.Отбор.ОсновноеСредство.Установить(Выборка.ОсновноеСредство);
// Удаляем регистрацию для конкретного узла
ПланыОбмена.УдалитьРегистрациюИзменений(Выборка.Узел, НаборЗаписей);
КонецЦикла;
Важный момент: Обратите внимание, что мы не вызываем метод Прочитать() для набора записей. В контексте данной задачи, когда самой записи в базе уже нет, этот вызов абсолютно избыточен. Платформа ориентируется исключительно на установленные свойства объекта Отбор переданного набора.
Разберем более элегантный альтернативный подход. В качестве второго параметра метод УдалитьРегистрациюИзменений() умеет принимать не только набор записей, но и объект РегистрСведенийКлючЗаписи. При удалении мусора этот способ зачастую работает надежнее, так как не требует имитации работы с данными через набор.
Посмотрим на пример реализации данного подхода:
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
// Формируем структуру со всеми измерениями (и периодом, если нужно)
СтруктураКлюча = Новый Структура;
СтруктураКлюча.Вставить("ОсновноеСредство", Выборка.ОсновноеСредство);
// Создаем ключ записи
КлючЗаписи = Новый РегистрСведенийКлючЗаписи.ПервоначальныеСведения(СтруктураКлюча);
// Удаляем регистрацию по ключу
ПланыОбмена.УдалитьРегистрациюИзменений(Выборка.Узел, КлючЗаписи);
КонецЦикла;
Если ваша конфигурация разработана на базе Библиотеки стандартных подсистем (БСП), вам не обязательно писать код для разовой точечной очистки. Рассмотрим использование готового инструмента:
<Объект не найден>.Используя любой из предложенных методов, вы сможете эффективно поддерживать чистоту таблиц обмена и предотвращать возможные ошибки при синхронизации данных.