Как программно очистить справочник в 1С: эффективные методы и решение ошибок

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

В процессе сопровождения баз данных 1С программисты часто сталкиваются с необходимостью массового удаления записей. Это может быть связано с очисткой тестовых данных, исправлением последствий некорректного обмена или просто технологической необходимостью «обнулить» справочник, такой как Контрагенты или Номенклатура. Стандартная обработка «Удаление помеченных объектов» при огромных объемах (сотни тысяч и миллионы записей) работает крайне медленно. В таких случаях на помощь приходит программный код. Если перед вами стоит задача полностью очистить базу от сведений конкретного юридического лица, для этого используют инструмент выборочного удаления организаций в 1С.

Однако просто написать цикл удаления бывает недостаточно: можно столкнуться с ошибками синтаксиса, блокировками базы данных или катастрофически низкой скоростью работы. Рассмотрим подробно, как правильно решать задачу очистки справочника.

Разбор ошибки «Ожидается выражение ВЫБРАТЬ»

Разберем ситуацию, с которой столкнулся автор темы. При попытке выполнить простейший код выборки объектов платформа выдает синтаксическую ошибку. Проанализируем причину. Фраза «Ожидается выражение ВЫБРАТЬ» (Expected SELECT) характерна для Языка запросов 1С. Если вы видите ее при выполнении программного кода, это обычно означает одно из двух:

  1. Выполнение кода в консоли запросов: Вы пытаетесь запустить процедурный код (циклы Пока...Цикл, условия Если) в инструменте, предназначенном исключительно для текстов запросов. Консоль запросов ожидает, что текст начнется со слова ВЫБРАТЬ.
  2. Конфликт имен переменных: Использование зарезервированных слов или имен объектов метаданных в качестве имен переменных. Например, использование переменной Объект в модуле формы или использование имени, совпадающего с методом встроенного языка.

Чтобы исправить это, убедитесь, что вы запускаете код во внешней обработке или специализированной «Консоли кода» (не путать с консолью запросов). Также рекомендуется использовать уникальные префиксы для переменных, например, ТекОбъект вместо просто Объект.

Метод 1. Удаление через объектную выборку (для небольших справочников)

Рассмотрим базовый вариант удаления. Он подходит, если количество записей исчисляется тысячами, а не миллионами. Выясним, как сделать этот код стабильнее. Важно учитывать иерархию справочника: если у справочника есть группы, обычная выборка может работать некорректно при удалении родителей раньше детей.


ВыборкаДетальныеЗаписи = Справочники.Контрагенты.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
    ТекОбъект = ВыборкаДетальныеЗаписи.ПолучитьОбъект();
    // Отключаем проверки, чтобы ускорить процесс и избежать отказов
    ТекОбъект.ОбменДанными.Загрузка = Истина; 
    Попытка
        ТекОбъект.Удалить();
    Исключение
        Сообщить("Не удалось удалить объект: " + ТекОбъект.Ссылка + " Ошибка: " + ОписаниеОшибки());
    КонецПопытки;
КонецЦикла;

Обратите внимание на свойство ОбменДанными.Загрузка = Истина. Это критически важный момент. Установка этого флага отключает выполнение всех проверок в модуле объекта (события ПередЗаписью, ПриЗаписи, ПередУдалением). Это не только ускоряет процесс в разы, но и позволяет удалять объекты, которые не проходят бизнес-логику системы.

Метод 2. Порционное удаление через запрос (для больших объемов)

Когда объектов «архи много», попытка получить одну огромную выборку может привести к переполнению памяти или длительным блокировкам таблиц. Проанализируем ситуацию: эффективнее выбирать ссылки порциями, удалять их и повторять цикл до полной очистки. Посмотрим на пример реализации:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ ПЕРВЫЕ 1000
    |	Контрагенты.Ссылка КАК Ссылка
    |ИЗ
    |	Справочник.Контрагенты КАК Контрагенты";

Пока Истина Цикл
    РезультатЗапроса = Запрос.Выполнить();
    Если РезультатЗапроса.Пустой() Тогда
        Прервать;
    КонецЕсли;
    
    Выборка = РезультатЗапроса.Выбрать();
    Пока Выборка.Следующий() Цикл
        ТекОбъект = Выборка.Ссылка.ПолучитьОбъект();
        Если ТекОбъект <> Неопределено Тогда
            ТекОбъект.ОбменДанными.Загрузка = Истина;
            ТекОбъект.Удалить();
        КонецЕсли;
    КонецЦикла;
КонецЦикла;

Этот метод позволяет базе данных «дышать» между итерациями. Если процесс прервется, часть данных уже будет удалена, и вы сможете продолжить с того же места.

Метод 3. Использование транзакций для ускорения

Выясним причину медленной работы стандартного удаления. По умолчанию каждое выполнение метода Удалить() инициирует отдельную транзакцию в SQL-сервере. Открытие и закрытие транзакции — ресурсоемкая операция. Если мы объединим удаление 1000 объектов в одну транзакцию, скорость возрастет в десятки раз.

Разберем, как реализовать это правильно:


НачатьТранзакцию();
Счетчик = 0;
// ... код выборки из Метода 2 ...
Пока Выборка.Следующий() Цикл
    ТекОбъект = Выборка.Ссылка.ПолучитьОбъект();
    ТекОбъект.ОбменДанными.Загрузка = Истина;
    ТекОбъект.Удалить();
    
    Счетчик = Счетчик + 1;
    Если Счетчик % 1000 = 0 Тогда
        ЗафиксироватьТранзакцию();
        НачатьТранзакцию();
    КонецЕсли;
КонецЦикла;
ЗафиксироватьТранзакцию();

Важно: Не пытайтесь удалить весь справочник в одной транзакции, если в нем сотни тысяч записей. Это может привести к разрастанию лога транзакций SQL-сервера и блокировке всей базы для других пользователей.

Метод 4. Высокопроизводительный метод «УдалитьОбъекты» (Платформа 8.3.18+)

В современных версиях платформы 1С появился метод УдалитьОбъекты, который является наиболее быстрым способом удаления данных средствами встроенного языка. Он работает на уровне, близком к SQL-запросам, и минимизирует количество обращений к серверу БД.

Рассмотрим, как его использовать. Метод принимает массив ссылок и позволяет удалять их массово:


МассивСсылок = Новый Массив;
// Заполняем массив ссылками через запрос
// ...
Справочники.Контрагенты.УдалитьОбъекты(МассивСсылок, Истина); // Истина - удалять без проверки ссылочной целостности

Этот метод работает значительно быстрее, чем цикл с ПолучитьОбъект(), так как не создает объектную модель в памяти для каждой записи.

Рекомендации и предостережения

Проанализируем сопутствующие риски при полной очистке справочника:

Таким образом, для безопасной и быстрой очистки справочника мы рекомендуем использовать комбинацию Запроса для выборки порций ссылок и метода УдалитьОбъекты (или удаление в транзакциях с флагом ОбменДанными.Загрузка), если версия платформы не позволяет использовать новые методы.

← На главную