Как в 1С программно удалить запись регистра сведений по ключу?

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

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

Понимаем разницу между Ключом, Менеджером и Набором записей

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

  1. РегистрСведенийКлючЗаписи: Это своего рода «визитная карточка» записи. Он содержит только значения измерений и период (для периодических регистров). В нем нет ресурсов или реквизитов. Главная задача ключа — служить уникальным идентификатором, который можно легко передавать между клиентом и сервером.
  2. РегистрСведенийМенеджерЗаписи: Это «рабочий инструмент» для взаимодействия с конкретной, одной единственной записью. Он позволяет читать данные, изменять их и, самое главное, удалять. Однако важно помнить: менеджер записи работает только с независимыми регистрами сведений.
  3. РегистрСведенийНаборЗаписей: Универсальный и самый мощный механизм. Он работает с коллекциями строк, отобранных по определенному критерию. Платформа всегда использует наборы записей «под капотом», даже когда вы работаете через менеджер.

Способ №1: Использование Менеджера записи (для независимых регистров)

Если наш регистр является независимым, самый простой и читаемый способ — использовать МенеджерЗаписи. Рассмотрим, как связать полученный ключ с менеджером и выполнить удаление. Проанализируем универсальный подход, который будет работать на всех версиях платформы, начиная с 8.1 и заканчивая актуальными релизами 8.3.

Для этого мы создаем экземпляр менеджера записи и «переносим» в него значения измерений из ключа. Самый надежный способ сделать это — воспользоваться функцией ЗаполнитьЗначенияСвойств.


// Предположим, ПереданныйКлюч — это объект типа РегистрСведенийКлючЗаписи
МенеджерЗаписи = РегистрыСведений.НазваниеВашегоРегистра.СоздатьМенеджерЗаписи();

// Копируем значения измерений из ключа в менеджер
ЗаполнитьЗначенияСвойств(МенеджерЗаписи, ПереданныйКлюч);

// Удаляем запись из базы данных
МенеджерЗаписи.Удалить();

Важный нюанс: В некоторых версиях платформы (особенно в 8.3) у менеджера записи есть метод Заполнить(), который может принимать ключ записи напрямую. Однако, как показывает практика обсуждений на форумах, в старых конфигурациях или специфических сборках этот метод может отсутствовать или работать некорректно. Поэтому использование ЗаполнитьЗначенияСвойств считается «золотым стандартом» надежности.

Способ №2: Использование Набора записей (универсальный метод)

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

Выясним, как это работает на практике. Когда мы устанавливаем отбор в наборе записей и вызываем метод Записать(), система заменяет в базе данных все записи, подходящие под этот отбор, на те, что содержатся в наборе. Если набор пуст — записи просто удаляются.


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

// Устанавливаем фильтры по всем измерениям, которые есть в ключе
НаборЗаписей.Отбор.Измерение1.Установить(ПереданныйКлюч.Измерение1);
НаборЗаписей.Отбор.Измерение2.Установить(ПереданныйКлюч.Измерение2);

// Если регистр периодический, не забудьте про Период
// НаборЗаписей.Отбор.Период.Установить(ПереданныйКлюч.Период);

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

Этот метод особенно эффективен, если вам нужно удалить не одну запись, а группу записей, объединенных общим значением какого-либо измерения.

Разбор критической ошибки: Почему нельзя удалять через Запрос и Загрузить()

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

В чем заключается опасность? Представим сценарий:

  1. Вы выполняете запрос и получаете 100 записей, которые хотите «оставить».
  2. В этот же микросекундный момент другой пользователь или фоновое задание добавляет в регистр 101-ю запись.
  3. Вы загружаете свои 100 записей в НаборЗаписей и записываете его.

Результат: 101-я запись будет безвозвратно удалена, так как она не попала в ваш запрос, а набор записей при записи заменяет все данные в рамках установленного отбора (или вообще все данные в регистре, если отбор не установлен).

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

Особенности подчиненных регистров (по регистратору)

Если ваш регистр сведений имеет режим записи «Подчинение регистратору», то ни метод с МенеджерЗаписи, ни прямая установка отборов по измерениям в наборе записей не позволят вам удалить строку. В таких регистрах жизнь записи жестко связана с документом-регистратором.

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

  1. Создать набор записей.
  2. Установить отбор только по Регистратору.
  3. Прочитать набор (метод Прочитать()).
  4. Найти в полученной коллекции (таблице) нужную строку по значениям её измерений.
  5. Удалить строку из коллекции набора.
  6. Записать набор.

Производительность и блокировки

Выясним, какой способ быстрее. Если вам нужно удалить одну запись, разница между менеджером и набором минимальна. Однако, если задача стоит в удалении 10 000 записей по списку ключей, выполнение МенеджерЗаписи.Удалить() в цикле будет крайне медленным. Каждое такое удаление — это отдельная транзакция и отдельное обращение к серверу БД.

В целях оптимизации рекомендуем:

Подводя итог, можно сказать, что наиболее универсальным и безопасным способом удаления записи по ключу является использование Менеджера записи с предварительным заполнением через ЗаполнитьЗначенияСвойств. Это решение прозрачно, надежно и легко поддается отладке.

← На главную