Как загрузить данные из внешней СУБД в регистр сведений 1С без перезаписи и дублирования

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

При интеграции 1С с внешними системами (например, при периодической загрузке логов через ADODB) разработчики часто сталкиваются с ситуацией, когда повторный запуск процедуры либо полностью очищает существующие записи в регистре сведений, либо дублирует их. Рассмотрим причины этого поведения и проанализируем решения этой задачи.

Выясним причину: почему очищается регистр сведений

Разберем стандартный алгоритм работы с объектом РегистрСведенийНаборЗаписей. Когда мы создаем новый набор записей с помощью метода СоздатьНаборЗаписей(), он изначально пуст и не содержит никаких отборов.

Посмотрим на типичный фрагмент кода, приводящий к полной перезаписи регистра:


&НаСервере
Процедура ДобавлениеЗаписиВРегистр(ТЗ)

    НаборЗаписей = РегистрыСведений.ЛогиТМГ.СоздатьНаборЗаписей();

    Для Каждого Строка Из ТЗ Цикл
        Запись = НаборЗаписей.Добавить();
        ЗаполнитьЗначенияСвойств(Запись, Строка);
    КонецЦикла;

    // Вызов метода Записать() по умолчанию использует параметр Замещать = Истина
    НаборЗаписей.Записать();

КонецПроцедуры

Метод Записать() объекта РегистрСведенийНаборЗаписей принимает булевый параметр Замещать, значение которого по умолчанию равно Истина. Если у набора записей независимого регистра сведений не установлен отбор по измерениям, вызов Записать() полностью стирает все данные в регистре и записывает только те строки, которые находятся в текущем наборе в данный момент.

Важно: В независимом регистре сведений отбор в наборе записей можно установить только по измерениям. Установить отбор по ресурсам или реквизитам платформой 1С запрещено.

Способ 1. Запись с параметром Замещать = Ложь

Чтобы добавить новые данные к уже существующим без предварительной очистки регистра, следует явно передать значение Ложь в метод Записать():


&НаСервере
Процедура ДобавитьНовыеЗаписи(ТЗ)

    НаборЗаписей = РегистрыСведений.ЛогиТМГ.СоздатьНаборЗаписей();

    Для Каждого Строка Из ТЗ Цикл
        Запись = НаборЗаписей.Добавить();
        ЗаполнитьЗначенияСвойств(Запись, Строка);
    КонецЦикла;

    // Режим добавления записей без перезаписи регистра
    НаборЗаписей.Записать(Ложь);

КонецПроцедуры

При вызове НаборЗаписей.Записать(Ложь) платформа попытается добавить новые строки к имеющимся в базе данных. Однако здесь необходимо учитывать ключевое правило платформы 1С:

Уникальность строк в регистре сведений определяется строго комбинацией значений его измерений (и периода, если регистр периодический). Если вы передадите запись, комбинация измерений которой уже существует в базе, платформа вызовет ошибку необрабатываемого исключения (нарушение уникальности данных).

Для корректной работы этого метода убедимся, что ключевые параметры лога (например, дата/время события, имя сервера, порядковый номер) назначены именно Измерениями регистра, а не ресурсами.

Способ 2. Проверка и запись через Менеджер записи

Если требуется проверять существование каждой конкретной записи перед сохранением, удобнее использовать Менеджер записи. Посмотрим, как реализовать этот подход пошагово:

  1. Создаем объект СоздатьМенеджерЗаписи() для соответствующего регистра.
  2. Заполняем ключевые поля (измерения).
  3. Вызываем метод Прочитать().
  4. Проверяем результат с помощью метода Выбран(). Если метод возвращает Ложь, значит, такой записи в базе еще нет — заполняем остаток полей и вызываем Записать().

Проанализируем пример кода:


&НаСервере
Процедура ЗаписатьЧерезМенеджер(ТЗ)

    Для Каждого Строка Из ТЗ Цикл

        МенеджерЗаписи = РегистрыСведений.ЛогиТМГ.СоздатьМенеджерЗаписи();

        // Указываем значения измерений для поиска
        МенеджерЗаписи.GMTlog = Строка.GMTlog;
        МенеджерЗаписи.SrvName = Строка.SrvName;
        МенеджерЗаписи.NUM = Строка.NUM;

        // Пытаемся прочитать существующую запись
        МенеджерЗаписи.Прочитать();

        // Записываем только если запись не была найдена
        Если НЕ МенеджерЗаписи.Выбран() Тогда
            ЗаполнитьЗначенияСвойств(МенеджерЗаписи, Строка);
            МенеджерЗаписи.Записать();
        КонецЕсли;

    КонецЦикла;

КонецПроцедуры

Способ 3. Оптимизация выборки на стороне внешней СУБД

Загрузка полного объема логов во временную таблицу значений при каждом запуске обработки создает значительную нагрузку на оперативную память и снижает быстродействие системы. Чтобы оптимизировать процесс, применим фильтрацию еще на этапе запроса к внешней СУБД:

  1. Сохраняем в 1С (в константе или дополнительном регистре) дату и время последней успешно загруженной записи.
  2. В SQL-запросе к внешней БД через ADO добавляем условие отбора по дате (например, WHERE GmtLogTime > @LastLoadedTime).
  3. Получаем и записываем в 1С только те строки, которые появились во внешней СУБД с момента предыдущего сеанса загрузки.
← На главную