К статье
Практический материал

Разработка и Конфигурация · 10 мин

Как удалить результат запроса в 1С

Как удалить данные, полученные запросом 1С: удаление объектов через запрос, пакетные запросы, временные таблицы, типичные ошибки и проверка результата.

Запрос в 1С сам по себе ничего не удаляет: язык запросов предназначен только для чтения данных. Однако на практике под «удалением результата запроса» обычно понимают одну из трёх задач: удалить из базы объекты, которые вернул запрос; очистить временную таблицу в пакетном запросе; либо освободить память, занятую результатом запроса в коде. Каждая задача решается по-разному, и путать их нельзя.

Ниже разобраны все три сценария с примерами кода на встроенном языке 1С. Материал подходит для типовых и самописных конфигураций на управляемых и обычных формах — синтаксис запросов и работы с объектами одинаков.

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

Что именно вы хотите удалить: три разные задачи

Прежде чем писать код, определите, какая из задач стоит перед вами. Первая — физическое удаление из базы документов, элементов справочников или записей регистров, которые нашёл запрос. Это самый частый сценарий при чистке базы от тестовых или ошибочных данных.

Вторая задача — удалить временную таблицу внутри пакетного запроса, когда она больше не нужна и занимает память сервера. Третья — освободить оперативную память клиента или сервера, занятую выборкой или таблицей значений после обработки результата.

Маршрут решения

Как выбрать действие

Нужно удалить из базы документы или элементы справочников, найденные запросомПереберите выборку, получите объект по ссылке и вызовите Удалить()
В пакетном запросе накопилась ненужная временная таблицаДобавьте в пакет секцию УНИЧТОЖИТЬ ИмяТаблицы
После обработки результата в коде нужно освободить памятьПрисвойте переменной Неопределено или используйте выборку вместо Выгрузить()

Удаление объектов, найденных запросом

Основной приём: запрос возвращает ссылки, а удаление выполняется через объектное представление. Запрос выбирает поле Ссылка, затем в цикле по выборке или таблице значений вызывается Ссылка.ПолучитьОбъект(), и у объекта вызывается метод Удалить().

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| РеализацияТоваровУслуг.Ссылка КАК Ссылка

|ИЗ

| Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг

|ГДЕ

| РеализацияТоваровУслуг.Дата < &ДатаОтсечки";

Запрос.УстановитьПараметр("ДатаОтсечки", ДатаОтсечки);

Выборка = Запрос.Выполнить().Выбрать();

Пока Выборка.Следующий() Цикл

ДокОбъект = Выборка.Ссылка.ПолучитьОбъект();

ДокОбъект.Удалить();

КонецЦикла;

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

Удаление записей регистра сведений по результату запроса

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

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| КурсыВалют.Период КАК Период,

| КурсыВалют.Валюта КАК Валюта

|ИЗ

| РегистрСведений.КурсыВалют КАК КурсыВалют

|ГДЕ

| КурсыВалют.Период < &ДатаОтсечки";

Выборка = Запрос.Выполнить().Выбрать();

Пока Выборка.Следующий() Цикл

МенеджерЗаписи = РегистрыСведений.КурсыВалют.СоздатьМенеджерЗаписи();

МенеджерЗаписи.Период = Выборка.Период;

МенеджерЗаписи.Валюта = Выборка.Валюта;

МенеджерЗаписи.Прочитать();

Если МенеджерЗаписи.Выбран() Тогда

МенеджерЗаписи.Удалить();

КонецЕсли;

КонецЦикла;

Для большого объёма записей эффективнее работать наборами: создать набор записей с отбором, не загружать данные и вызвать Записать() пустого набора — все записи по отбору будут удалены одной операцией. Это заметно быстрее поштучного удаления, но требует аккуратности с отбором: пустой набор без отбора удалит весь регистр.

Удаление временной таблицы в пакетном запросе

В пакетных запросах промежуточные результаты помещаются во временные таблицы командой ПОМЕСТИТЬ ИмяТаблицы. Все временные таблицы живут в менеджере временных таблиц до конца выполнения всего пакета, даже если больше не используются, и занимают память сервера СУБД.

Чтобы удалить временную таблицу, когда она отработала своё, добавьте в пакет отдельную секцию УНИЧТОЖИТЬ ИмяТаблицы. Секции пакетного запроса разделяются точкой с запятой.

Запрос.Текст =

"ВЫБРАТЬ

| Продажи.Номенклатура КАК Номенклатура,

| СУММА(Продажи.Количество) КАК Количество

|ПОМЕСТИТЬ ВТ_Продажи

|ИЗ

| РегистрНакопления.Продажи.Обороты(, , , ) КАК Продажи

|СГРУППИРОВАТЬ ПО

| Продажи.Номенклатура

|;

|

|ВЫБРАТЬ

| ВТ_Продажи.Номенклатура КАК Номенклатура

|ИЗ

| ВТ_Продажи КАК ВТ_Продажи

|ГДЕ

| ВТ_Продажи.Количество > 100

|;

|

|УНИЧТОЖИТЬ ВТ_Продажи";

После УНИЧТОЖИТЬ обращение к таблице в последующих секциях пакета вызовет ошибку «Таблица не найдена». Поэтому уничтожайте таблицу только после последнего обращения к ней. Если запрос выполняется один раз и временная таблица небольшая, явное уничтожение необязательно — менеджер временных таблиц очистится автоматически при уничтожении объекта запроса.

Освобождение памяти от результата запроса в коде

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

Чтобы удалить результат из памяти после обработки, присвойте переменной значение Неопределено. Сборщик мусора платформы освободит память, когда на таблицу не останется ссылок. Более экономичный вариант — вообще не выгружать результат, а обходить его выборкой через Выбрать(): выборка читает данные порциями и не держит всю таблицу в памяти.

Порядок безопасного удаления данных по запросу
  1. 1
    Сделайте резервную копию базы или выгрузку данных
  2. 2
    Напишите запрос и сначала выполните его без удаления — проверьте, что выбраны именно нужные записи
  3. 3
    Замените чтение на цикл с ПолучитьОбъект() и Удалить() или пометкой удаления
  4. 4
    Выполните удаление в тестовой копии базы и проверьте связанные данные
  5. 5
    Запустите обработку в рабочей базе, желательно вне пиковой нагрузки
  6. 6
    Проверьте результат повторным запросом — он должен вернуть пустой результат

Типичные ошибки при удалении результатов запроса

Самая частая ошибка — попытка удалить данные самим запросом, например написать в тексте запроса УДАЛИТЬ или DELETE. Язык запросов 1С не поддерживает модификацию данных, кроме УНИЧТОЖИТЬ для временных таблиц, и консоль запросов выдаст синтаксическую ошибку.

Вторая ошибка — удаление внутри цикла по выборке без транзакции при больших объёмах. Если обработка прервётся на середине, часть данных будет удалена, часть останется, и понять, где остановился процесс, будет сложно. Для массовых операций используйте транзакцию или порционную обработку с фиксацией прогресса.

Типичные ошибки
01
Попытка написать DELETE в тексте запроса — язык запросов 1С не изменяет данные, получите синтаксическую ошибку
02
Физическое удаление объектов без проверки ссылочной целостности — в базе появятся битые ссылки вида «Объект не найден»
03
Выгрузка огромного результата через Выгрузить() вместо обхода выборкой — переполнение памяти сервера
04
УНИЧТОЖИТЬ временной таблицы до последнего обращения к ней — ошибка «Таблица не найдена» в следующей секции пакета
05
Запись пустого набора записей регистра без отбора — удаление всех записей регистра целиком

Проверка результата после удаления

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

Если удалялись объекты, на которые могли ссылаться другие данные, выполните тестирование и исправление информационной базы с проверкой ссылочной целостности или используйте обработку поиска битых ссылок. Признаком проблемы служат записи вида «<Объект не найден>» в списках и отчётах.

Контрольные точки

Как проверить результат

Повторное выполнение исходного запроса
Норма

Выборка пустая — записей, подходящих под условие, не осталось

Тревожный признак

Запрос снова возвращает строки — удаление выполнено частично или условие в коде отличается

Списки документов и справочников
Норма

Нет записей «Объект не найден», отчёты открываются без ошибок

Тревожный признак

Появились битые ссылки — объекты удалены физически без контроля целостности

Временные таблицы после пакетного запроса
Норма

После УНИЧТОЖИТЬ обращений к таблице нет, запрос выполняется без ошибок

Тревожный признак

Ошибка «Таблица не найдена» — таблица уничтожена раньше последнего использования

FAQ

Можно ли удалить данные прямо в тексте запроса 1С?

Нет. Язык запросов 1С предназначен только для чтения данных. Единственная операция удаления внутри запроса — команда УНИЧТОЖИТЬ, и она работает исключительно с временными таблицами пакетного запроса, а не с данными базы.

Чем отличается Удалить() от пометки удаления?

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

Как удалить тысячи объектов, не блокируя базу надолго?

Обрабатывайте данные порциями: ограничьте выборку через РАЗЛИЧНЫЕ ПЕРВЫЕ или по диапазону дат, удаляйте порцию в отдельной транзакции и фиксируйте прогресс. Запускайте обработку в фоновом задании вне часов активной работы пользователей.

Нужно ли явно уничтожать временные таблицы после запроса?

Если менеджер временных таблиц не задан явно, все временные таблицы удаляются автоматически при уничтожении объекта запроса. Явное УНИЧТОЖИТЬ имеет смысл внутри длинного пакетного запроса, чтобы освободить память сервера СУБД до завершения всего пакета.

Что делать, если после удаления появились битые ссылки?

Восстановите данные из резервной копии, если она есть, и повторите удаление через пометку с контролем целостности. Если копии нет, запустите тестирование и исправление информационной базы с включённой проверкой ссылочной целостности — платформа предложит варианты обработки битых ссылок.

Итог

Что важно запомнить

Запрос 1С только читает данные. Удаление найденных объектов выполняется в коде через ПолучитьОбъект() и Удалить(), записей регистров — через менеджер записи или пустой набор с отбором, временных таблиц — командой УНИЧТОЖИТЬ. Перед массовым удалением делайте резервную копию и предпочитайте пометку удаления с контролем ссылочной целостности.