Как удалить движения и итоги регистра по группе номенклатуры с помощью прямого запроса в 1С 7.7?

Программист 1С v7.7 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

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

Разберем по шагам, как правильно подготовить список объектов, передать его во временную таблицу SQL, корректно составить инструкцию DELETE для таблиц движений и итогов, а также избежать критических ошибок при выполнении запроса.

Подготовка списка номенклатуры и передача во временную таблицу

Для фильтрации данных по иерархии справочника необходимо собрать список целевых элементов. Метод УложитьСписокОбъектов компоненты ODBCRecordSet позволяет передать список значений 1С напрямую во временную таблицу SQL (например, #СписокНоменклатуры), к которой затем можно обращаться через оператор IN или объединения JOIN.

Рассмотрим пример формирования списка и создания объекта прямого запроса:


Запрос = СоздатьОбъект("ODBCRecordSet");

// Передаем сформированный список групп/элементов во временную таблицу SQL
Запрос.УложитьСписокОбъектов(МойСписокНоменклатуры, "#СписокНоменклатуры", "Номенклатура");

Предварительная проверка данных перед удалением

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

Выясним разницу между методами выполнения запросов в 1С++:

  1. ВыполнитьИнструкцию — возвращает полную таблицу значений (ТаблицаЗначений) или индексированную таблицу, что удобно для визуального просмотра строк.
  2. ВыполнитьСкалярный — возвращает единственное скалярное значение (или структуру при выборе нескольких колонок первой строки). Идеально подходит для подсчета количества строк через агрегатную функцию COUNT(*) или выполнения команд модификации данных (DELETE, UPDATE).

Посмотрим на пример предварительного просмотра записей в таблице значений:


ТекстЗапросаСелект = "
|SELECT * 
|FROM $Регистр.ПартииНаличие AS ПартииНаличие
|WHERE $ПартииНаличие.Номенклатура IN (SELECT val FROM #СписокНоменклатуры)
|";

ТЗ = Запрос.ВыполнитьИнструкцию(ТекстЗапросаСелект);
ТЗ.ВыбратьСтроку("Записи регистра, подлежащие удалению");

Если требуется быстро узнать только количество удаляемых записей, используем конструкцию со скалярным запросом:


ТекстКоличество = "
|SELECT COUNT(*) 
|FROM $Регистр.ПартииНаличие AS ПартииНаличие
|WHERE $ПартииНаличие.Номенклатура IN (SELECT val FROM #СписокНоменклатуры)
|";

КоличествоЗаписей = Запрос.ВыполнитьСкалярный(ТекстКоличество);
Сообщить("Будет удалено записей: " + КоличествоЗаписей);

Синтаксис DELETE в T-SQL и удаление движений и итогов

При выполнении команд удаления в Microsoft SQL Server часто возникает ошибка State 42000, native 156, message Неправильный синтаксис около ключевого слова 'AS'. В диалекте T-SQL при удалении нельзя указывать псевдоним таблицы напрямую через конструкцию DELETE FROM Таблица AS Псевдоним.

Проанализируем корректные варианты написания запроса:

  1. Без использования псевдонима: обращение к метаименам 1С++ строится напрямую от имени регистра.
  2. С явным псевдонимом: синтаксис требует указания алиаса сразу после команды DELETE, например: DELETE Псевдоним FROM Таблица AS Псевдоним WHERE ....

Рассмотрим рабочий код очистки таблицы движений ($Регистр.ПартииНаличие) и таблицы периодических итогов ($РегистрИтоги.ПартииНаличие):


ТекстУдаления = "
|DELETE FROM $Регистр.ПартииНаличие
|WHERE $Регистр.ПартииНаличие.Номенклатура IN (SELECT val FROM #СписокНоменклатуры)
|
|DELETE FROM $РегистрИтоги.ПартииНаличие
|WHERE $РегистрИтоги.ПартииНаличие.Номенклатура IN (SELECT val FROM #СписокНоменклатуры)
|";

Запрос.ВыполнитьСкалярный(ТекстУдаления);
Сообщить("Удаление движений и итогов успешно завершено.");

Решение проблемы с переполнением журнала транзакций (Error 9002)

При массовом удалении сотен тысяч строк в одной транзакции Microsoft SQL Server активно логирует каждую операцию, что приводит к ошибке: Журнал транзакций для базы данных заполнен (native 9002).

Разберем действия для устранения и предотвращения этой ошибки:

  1. Увеличение размера и авторасширения файла LDF: через SQL Server Management Studio (SSMS) откройте свойства базы данных, перейдите в раздел Files (Файлы) и проверьте ограничение максимального размера для файла журнала транзакций (LOG), а также наличие свободного места на физическом диске.
  2. Усечение журнала транзакций: при простой модели восстановления (Simple Recovery Model) выполните операцию сжатия файла лога (DBCC SHRINKFILE).
  3. Пакетное удаление (порциями): для предотвращения блокировки таблиц и чрезмерного роста журнала транзакций выполняйте операцию порциями с ограничением DELETE TOP (N) в цикле до полной очистки.

Важные риски прямого удаления данных

Прямое вмешательство в таблицы базы данных в обход объектной модели платформы 1С 7.7 требует повышенной осторожности. Учитывайте следующие особенности архитектуры:

  1. Целостность документов: удаление записей из таблиц движений (RA...) и итогов (RG...) не изменяет флаги проведенности и табличные части самих документов. При любой последующей перепроводке документов платформа заново запишет движения в регистр.
  2. Подчиненные справочники и связанные регистры: в типовых конфигурациях (например, «Торговля и Склад 7.7») регистр партий тесно связан с подчиненным справочником «Партии» и регистрами взаиморасчетов. Простое удаление записей из одного регистра оставляет неиспользуемые «хвосты» в справочниках.
  3. Пересчет итогов: если записи удалены одновременно из движений и итогов по всем измерениям выбранной номенклатуры, штатная процедура пересчета итогов («Тестирование и исправление») отработает корректно. Однако если удалить записи только из итогов, при первой же регламентной процедуре платформа пересчитает итоги заново на основании оставшихся движений.
← На главную