Очистка регистра сведений: набором записей и через документы
Содержание
Почистить регистр сведений
в 1С 8.3 можно двумя путями, и выбор зависит от одного свойства — подчинён регистр регистратору или нет. Независимый регистр чистят набором записей: создают пустой набор без отбора и вызывают Записать(), платформа удаляет все строки. Регистр, подчинённый документу, так не трогают — его записи принадлежат регистратору, и убирают их отменой проведения или удалением самих документов.
Частая ошибка — пытаться удалить записи из консоли запросов. Запрос только читает данные, строк он не удаляет. Чтобы очистить регистр , нужен код: внешняя обработка или консоль кода, где отрабатывает набор записей.
Перед массовым удалением сделайте резервную копию базы
. Операция необратима: отменить Записать() по уже очищенному регистру нельзя — только восстановить из копии.
Сначала определите вид регистра
До любых действий посмотрите в Конфигураторе два свойства регистра сведений:
- 🔹 Режим записи —
НезависимыйилиПодчинение регистратору. Это главное, что определяет способ очистки. - 🔹 Периодичность —
Непериодическийили с периодом (в пределах секунды, дня, месяца и т. д.). Влияет на отбор и на виртуальные таблицы срезов.
Если доступа в Конфигуратор нет, вид определяют по поведению. Записи появляются и исчезают при проведении документов — значит, регистр подчинён регистратору. Записи заводят вручную через список или обменом — независимый.
Заодно посмотрите на состав регистра, чтобы понимать, что именно удаляете:
- 📐 Измерения — ключ записи. По ним ставят отбор при частичной очистке. У периодического регистра в ключ входит ещё и период.
- 📊 Ресурсы и реквизиты — значения, которые хранит запись. На способ очистки не влияют, но по ним бывает удобно отбирать записи запросом.
- 🔗 Ведущее измерение. Если у измерения стоит свойство
Ведущее, запись регистра удаляется автоматически вместе с объектом, на который она ссылается. Иногда «лишние» записи проще убрать, удалив ведущий объект, а не чистя регистр руками.
Полезно заранее прикинуть объём — сколько строк предстоит удалить. Это делает простой запрос:
Запрос = Новый Запрос("ВЫБРАТЬ КОЛИЧЕСТВО(*) КАК Всего ИЗ РегистрСведений.КурсыВалют");
Всего = Запрос.Выполнить().Выбрать();
Всего.Следующий();
Сообщить("Записей в регистре: " + Всего.Всего);
Если счёт идёт на сотни тысяч или миллионы строк, сразу планируйте удаление порциями и обслуживание базы после — об этом ниже.
Записать(). Можно отобрать по измерению и удалить только часть строк.СрезПоследних и СрезПервых пересчитывать не нужно — это виртуальные таблицы, они считаются на лету.Очистка независимого регистра в режиме «1С:Предприятие»
Для небольшого числа строк Конфигуратор не нужен. Откройте регистр прямо в пользовательском режиме.
- Включите команду «Все функции»: главное меню (значок со стрелкой вниз слева вверху) →
Настройки→Параметры→ поставьте галкуОтображать команду «Все функции». - Откройте главное меню →
Все функции→ раскройте веткуРегистры сведений→ выберите нужный регистр. - В списке выделите строки (можно
Ctrl+Aдля всех на текущей странице) и удалите клавишейDeleteили командой удаления в командной панели списка.
Способ годится, пока записей десятки или сотни. Выделять и удалять тысячи строк вручную неудобно и долго — для таких объёмов пишут обработку с кодом (следующий раздел).
Если строки в списке не удаляются и команда удаления недоступна — регистр почти наверняка подчинён регистратору. Такие записи редактируются только через документы.
Очистка набором записей из кода
Это основной способ для независимых регистров. Запускают его из внешней обработки или из консоли кода в режиме «1С:Предприятие».
Внешнюю обработку
(файл .epf) с кодом открывают через Файл → Открыть и выполняют её команду. В типовых конфигурациях для этого есть отдельный механизм дополнительных обработок, но для разовой очистки достаточно открыть обработку файлом. Сам код из примеров ниже кладут в модуль обработки или в поле консоли кода и запускают.
Полная очистка регистра — пустой набор без отбора:
Набор = РегистрыСведений.КурсыВалют.СоздатьНаборЗаписей();
// отбор не установлен → будут удалены все записи регистра
Набор.Записать(Истина); // Замещение = Истина
Запись набора замещает в базе строки, попадающие под его отбор, строками самого набора. Отбор пустой, набор пустой — значит, удаляются все записи и не добавляется ничего.
Чтобы убрать не весь регистр, а часть, установите отбор по измерению:
Набор = РегистрыСведений.КурсыВалют.СоздатьНаборЗаписей();
Набор.Отбор.Валюта.Установить(ВыбраннаяВалюта);
Набор.Записать(Истина); // удалятся записи только по этой валюте
Запись набора без отбора по большому регистру — это одна длинная транзакция. В рабочей базе она держит блокировки и мешает пользователям. Делайте массовую очистку в нерабочее время, а очень большие регистры удаляйте порциями — например, в цикле по значениям ключевого измерения, с отдельным Записать() на каждую порцию.
Порционная очистка выглядит так: сначала запросом берём различные значения измерения, потом по каждому чистим отдельным набором:
Запрос = Новый Запрос("ВЫБРАТЬ РАЗЛИЧНЫЕ Валюта ИЗ РегистрСведений.КурсыВалют");
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Набор = РегистрыСведений.КурсыВалют.СоздатьНаборЗаписей();
Набор.Отбор.Валюта.Установить(Выборка.Валюта);
Набор.Записать(Истина);
КонецЦикла;
Транзакций становится столько, сколько значений измерения, зато каждая короткая и блокирует только свою часть регистра.
Монопольный доступ к базе для такой очистки не нужен — набор записей пишется и в обычном многопользовательском режиме. Монополия потребовалась бы при изменении структуры регистра в Конфигураторе или при реструктуризации, но не при удалении данных. Тем не менее из-за блокировок массовую очистку всё равно удобнее делать, когда в базе никто не работает .
Консоль запросов для удаления не подходит: язык запросов умеет только выбирать данные. Запрос пригодится, чтобы заранее отобрать ключи записей на удаление, а само удаление делает набор записей.
Регистр, подчинённый регистратору: чистим через документы
У подчинённого регистра каждая запись привязана к документу-регистратору. Отдельно от документа её не существует, поэтому «почистить список» не выйдет — нужно работать с регистраторами.
Варианты по ситуации:
- 📄 Снять проведение документов. Записи регистра создаются при проведении. Отмена проведения убирает движения, в том числе по этому регистру сведений. Подходит, когда документы остаются в базе.
- 🗑️ Удалить документы . Если сами документы больше не нужны — пометьте на удаление и запустите удаление помеченных объектов. Движения уйдут вместе с регистраторами.
- 🔧 Очистить движения одного регистратора кодом. Установите в наборе отбор по регистратору и запишите пустой набор:
Набор = РегистрыСведений.СостоянияДоговоров.СоздатьНаборЗаписей();
Набор.Отбор.Регистратор.Установить(СсылкаНаДокумент);
Набор.Записать(Истина); // удалит движения этого документа по регистру
Последний приём применяют осторожно: записи регистра перестанут соответствовать проведённому документу. Если документ потом перепровести, движения вернутся.
Когда записи регистра «разошлись» с документами (например, после ручных правок), надёжнее не чистить регистр, а перепровести документы за период. Перепроведение заново формирует корректные движения по всем регистрам документа, включая этот регистр сведений. В типовых для этого есть групповое перепроведение документов за выбранный интервал.
Периодические регистры сведений: период и срезы
У периодического регистра в ключ записи входит период. В наборе записей появляется отбор Период, и им пользуются при точечной очистке.
Удалить сразу все записи старше определённой даты одним отбором нельзя: отбор набора работает на равенство, а не на диапазон. Порядок такой:
- Запросом отберите записи до нужной даты — вам нужны их ключи: значения измерений и период.
- В цикле по результату для каждого ключа установите отбор набора (измерения + период) и запишите пустой набор.
На практике это тот же порционный цикл, только в запросе добавляется условие по периоду, а в отбор набора — сам период:
Запрос = Новый Запрос(
"ВЫБРАТЬ РАЗЛИЧНЫЕ Период, Валюта
|ИЗ РегистрСведений.КурсыВалют
|ГДЕ Период < &ДатаОтсечки");
Запрос.УстановитьПараметр("ДатаОтсечки", ДатаОтсечки);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Набор = РегистрыСведений.КурсыВалют.СоздатьНаборЗаписей();
Набор.Отбор.Период.Установить(Выборка.Период);
Набор.Отбор.Валюта.Установить(Выборка.Валюта);
Набор.Записать(Истина);
КонецЦикла;
Так свежие записи остаются нетронутыми, а история до отсечки очищается.
Виртуальные таблицы СрезПоследних и СрезПервых после удаления строк отдельно пересчитывать не надо — это не хранимые итоги, а выборки, которые платформа строит на лету из оставшихся записей. Срез просто начнёт показывать то, что осталось.
Что сделать с базой после массового удаления
Сначала развеем частое заблуждение: у регистра сведений нет итогов, пересчитывать нечего. Пересчёт итогов — это про регистры накопления и бухгалтерии. У сведений хранятся только сами записи.
После удаления большого объёма освобождается место, но физически таблицы обслуживает СУБД, а не платформа. Что имеет смысл сделать:
- 🧹 Тестирование и исправление информационной базы. В Конфигураторе —
Администрирование→Тестирование и исправление. Для чистки после массового удаления полезен пунктРеиндексация таблиц информационной базы. - 💾 Файловая база. Дополнительно к реиндексации проверьте целостность утилитой
chdbfl.exe(при закрытой базе). - 🖥️ Клиент-серверная база. На стороне СУБД обновите статистику и при необходимости перестройте индексы освободившихся таблиц — так планы запросов останутся адекватными.
- 📉 Свободное место. Проверьте, что место на диске и в файле/базе данных действительно освободилось, особенно если удаляли миллионы строк.
В клиент-серверном варианте само по себе удаление строк не всегда возвращает место файлу базы данных: пространство помечается как свободное внутри СУБД, но физический размер файла может не уменьшиться. Если задача именно в том, чтобы вернуть место на диск, этим занимаются средствами СУБД (сжатие/перестроение), а не из 1С. Операцию согласуют с администратором сервера и выполняют в обслуживаемое окно.
Автоматизация регулярной очистки
Если регистр нужно подчищать постоянно — например, держать только последние несколько месяцев, — заводят регламентное задание.
Механизм такой:
- В Конфигураторе создают процедуру в общем модуле (с флагом
Сервер), которая удаляет записи старше вычисленной даты отсечки — тем же способом, что описан для периодических регистров. - Создают регламентное задание и привязывают к нему эту процедуру.
- Задают расписание — обычно раз в сутки ночью.
Дату отсечки процедура считает от текущей даты, чтобы глубина хранения оставалась постоянной:
Процедура ОчиститьСтарыеЗаписи() Экспорт
ДатаОтсечки = ДобавитьМесяц(НачалоДня(ТекущаяДата()), -6); // хранить полгода
// ... далее порционное удаление записей с Период < ДатаОтсечки
КонецПроцедуры
С таким заданием регистр не разрастается, а старая история чистится сама, без ручных запусков.
В типовых конфигурациях расписание и состояние заданий видно в пользовательском режиме: раздел Администрирование → Обслуживание → Регламентные и фоновые задания (точное название пункта зависит от конфигурации).
В файловой базе регламентные задания выполняются, только пока открыт хотя бы один сеанс. В клиент-серверной их отрабатывает сервер по расписанию, сеанс пользователя для этого не нужен.
Типичные ошибки
- ❌ Удалять через консоль запросов. Запрос ничего не удаляет. Нужен код с набором записей.
- ❌ Чистить подчинённый регистр напрямую. Его записи принадлежат документам — убирайте через отмену проведения или удаление регистраторов.
- ❌ Ждать пересчёта итогов. У регистра сведений итогов нет. Если после очистки «неправильно считает» отчёт — ищите причину в отборе или в самих данных, а не в итогах.
- ❌ Очищать огромный регистр одной транзакцией в рабочее время. Длинные блокировки затронут пользователей. Делайте порциями и в нерабочие часы.
- ❌ Удалять без резервной копии. Восстановить очищенный регистр можно только из копии — других способов нет.