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