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