Разработка и Конфигурация · 9 мин
Как удалить запись из справочника 1С программно
Программное удаление элементов справочника в 1С: методы Удалить(), УстановитьПометкуУдаления, контроль ссылочной целостности, права и типичные ошибки.
Удаление элемента справочника в 1С программным способом — типовая задача при чистке данных, обменах и автоматической обработке номенклатуры. В распоряжении разработчика два разных механизма: пометка на удаление и непосредственное (физическое) удаление объекта из базы. Выбор между ними определяется тем, есть ли на элемент ссылки в других объектах и насколько критична потеря данных.
Ключевой принцип платформы: сначала получают объект через метод ПолучитьОбъект(), затем вызывают нужный метод удаления. Работа через ссылку напрямую невозможна — ссылка не позволяет изменять данные. Ниже разобраны оба способа, контроль ссылочной целостности, права доступа и типичные ошибки, которые приводят к потере данных или битым ссылкам.
Пометка на удаление — безопасный способ
Пометка на удаление — штатный двухэтапный механизм платформы. Элемент остаётся в базе, но исключается из стандартных выборок и помечается красным крестиком в интерфейсе. Окончательное удаление выполняется позже через обработку «Удаление помеченных объектов» с автоматическим контролем ссылочной целостности.
Минимальный код пометки элемента на удаление:
ЭлементОбъект = Справочники.Номенклатура.НайтиПоКоду("00000123").ПолучитьОбъект();
ЭлементОбъект.УстановитьПометкуУдаления(Истина);
Метод УстановитьПометкуУдаления() сам записывает объект, дополнительно вызывать Записать() не требуется. Для снятия пометки передайте Ложь. Если у справочника иерархия, пометка группы по умолчанию распространяется на подчинённые элементы — поведение регулируется вторым параметром метода.
СсылкаНаЭлемент = Справочники.Контрагенты.НайтиПоНаименованию("ООО Ромашка");
Если Не СсылкаНаЭлемент.Пустая() Тогда
ЭлементОбъект = СсылкаНаЭлемент.ПолучитьОбъект();
ЭлементОбъект.УстановитьПометкуУдаления(Истина);
КонецЕсли;Непосредственное удаление через метод Удалить()
Метод Удалить() физически удаляет запись из таблицы базы данных без контроля ссылочной целостности. Если на элемент ссылаются документы, регистры или другие справочники, в этих местах останутся «битые» ссылки вида «Объект не найден». Восстановить удалённый элемент штатными средствами нельзя — только из резервной копии.
ЭлементОбъект = Справочники.Номенклатура.НайтиПоКоду("00000123").ПолучитьОбъект();
ЭлементОбъект.Удалить();
Непосредственное удаление оправдано в ограниченных сценариях: очистка технических справочников, удаление только что созданных обработкой дублей, загрузка данных, где гарантированно нет ссылок. Во всех остальных случаях безопаснее пометка на удаление с последующей штатной обработкой.
Проверка ссылок перед удалением
Перед физическим удалением проверьте, используется ли элемент где-либо в базе. Для этого служит функция НайтиПоСсылкам(), которая возвращает таблицу всех объектов, содержащих указанную ссылку.
МассивСсылок = Новый Массив;
МассивСсылок.Добавить(СсылкаНаЭлемент);
НайденныеСсылки = НайтиПоСсылкам(МассивСсылок);
Если НайденныеСсылки.Количество() = 0 Тогда
СсылкаНаЭлемент.ПолучитьОбъект().Удалить();
Иначе
// Только пометка на удаление
СсылкаНаЭлемент.ПолучитьОбъект().УстановитьПометкуУдаления(Истина);
КонецЕсли;
Учтите, что НайтиПоСсылкам() при большом объёме базы выполняется заметное время — в массовых обработках выгоднее передавать в функцию сразу массив из сотен ссылок, а не вызывать её для каждого элемента отдельно.
- 1Найдите элемент по коду, наименованию или запросом и проверьте, что ссылка не пустая
- 2Выполните НайтиПоСсылкам() и оцените количество найденных ссылок
- 3Если ссылок нет — вызовите Удалить(), если есть — УстановитьПометкуУдаления(Истина)
- 4Запустите штатную обработку «Удаление помеченных объектов» в монопольном режиме
- 5Проверьте результат: элемент отсутствует в списке, а в связанных документах нет записей «Объект не найден»
Удаление через запрос и массовая обработка
Когда удалить нужно не один элемент, а пакет — например, все неиспользуемые позиции номенклатуры, — сначала выбирают ссылки запросом, затем обрабатывают их в цикле. Это быстрее, чем перебор через Выбрать(), и позволяет заранее отфильтровать помеченные или используемые элементы.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.ПометкаУдаления = ЛОЖЬ
| И Номенклатура.ЭтоГруппа = ЛОЖЬ";
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
ОбъектЭлемента = Выборка.Ссылка.ПолучитьОбъект();
ОбъектЭлемента.УстановитьПометкуУдаления(Истина);
КонецЦикла;
При массовой обработке оборачивайте пакет в транзакцию, если требуется принцип «всё или ничего», но помните: длинная транзакция блокирует таблицу и мешает работе пользователей. На больших объёмах разумнее обрабатывать порциями без единой транзакции с записью лога успешных и ошибочных элементов.
Права доступа и монопольный режим
Для удаления у пользователя должны быть права «Удаление» и «Интерактивное удаление» (для интерактивных действий) на конкретный справочник. При недостатке прав метод Удалить() выбросит исключение «Нарушение прав доступа». В регламентных заданиях код выполняется от имени служебного пользователя — проверьте его роли отдельно.
Непосредственное удаление не требует монопольного режима, в отличие от штатной обработки «Удаление помеченных объектов», которая в большинстве конфигураций запускается монопольно. При работе в многопользовательской базе учитывайте, что другой сеанс может заблокировать удаляемый объект — перехватывайте исключения через Попытка...Исключение.
Особенности иерархических и подчинённых справочников
Для иерархических справочников пометка группы по умолчанию помечает и все вложенные элементы. Если нужно пометить только группу, передайте вторым параметром Ложь: УстановитьПометкуУдаления(Истина, Ложь). Физическое удаление непустой группы не удалит подчинённые элементы автоматически — они останутся с ссылкой на несуществующего родителя.
Подчинённые справочники (например, «Единицы измерения» у номенклатуры) при физическом удалении владельца не удаляются платформой автоматически — их нужно обрабатывать отдельно. А вот при пометке владельца на удаление штатная обработка удаления помеченных объектов обычно учитывает такие связи через механизм критериев и настроек конфигурации.
Как проверить результат
Удалённые элементы отсутствуют или отображаются с пометкой
Элементы на месте — вероятно, не хватило прав или объект был заблокирован
Ссылки отображаются корректно
Надпись «Объект не найден» — элемент удалён физически при наличии ссылок
Записи об удалении без ошибок
Ошибки «Нарушение прав доступа» или конфликт блокировок
Частые вопросы
Чем пометка на удаление отличается от метода Удалить()?
Пометка на удаление лишь устанавливает признак у записи — данные остаются в базе и доступны для восстановления снятием пометки. Метод Удалить() стирает запись физически и без контроля ссылок, восстановить её можно только из резервной копии.
Почему возникает ошибка «Нарушение прав доступа» при удалении?
У пользователя нет права «Удаление» на данный справочник либо действие выполняется в привилегированном контексте с ограничениями. Проверьте роли пользователя или выполните код внутри УстановитьПривилегированныйРежим(Истина), если это допустимо по логике задачи.
Можно ли удалить элемент, на который есть ссылки в документах?
Технически метод Удалить() это позволяет, но в документах останутся битые ссылки «Объект не найден», что нарушит отчёты и проведение. Правильный путь — пометить элемент на удаление и запустить штатную обработку «Удаление помеченных объектов», которая покажет все места использования.
Как удалить все помеченные элементы программно?
Выберите запросом элементы с ПометкаУдаления = Истина, проверьте ссылки через НайтиПоСсылкам() и для элементов без ссылок вызовите Удалить(). Либо используйте процедуры общего модуля удаления помеченных объектов из БСП, если она встроена в конфигурацию.
Нужно ли вызывать Записать() после УстановитьПометкуУдаления()?
Нет, метод УстановитьПометкуУдаления() сам записывает объект в базу. Дополнительный вызов Записать() избыточен, а в некоторых случаях может повторно инициировать подписки на события записи.
Как удалить элемент справочника в фоновом задании?
Оформите логику удаления в серверной процедуре общего модуля с признаком выполнения на сервере и запустите её через ФоновыеЗадания.Выполнить(). Учтите, что фоновое задание работает от служебного пользователя — проверьте его права на удаление.
Что важно запомнить
Получайте объект через ПолучитьОбъект(), по умолчанию используйте УстановитьПометкуУдаления(), а метод Удалить() применяйте только после проверки ссылок через НайтиПоСсылкам(). Контролируйте права доступа и оборачивайте массовые операции в обработку исключений.