При работе с механизмами партионного учета или другими системами, использующими последовательности документов, разработчики часто сталкиваются с необходимостью управления границами. Одной из специфических и труднорешаемых задач является физическое удаление записи из таблицы границ последовательности. Рассмотрим подробнее, почему стандартный метод УстановитьГраницу() не справляется с этой задачей и какие существуют альтернативные способы решения проблемы.
Для начала проанализируем, как объект Последовательность устроен внутри платформы. Физически в базе данных под одну последовательность выделяется не одна, а минимум две таблицы:
Последовательность.ПартионныйУчетБУ, мы обращаемся именно к ней.Последовательность.ПартионныйУчетБУ.Границы.Проблема, описанная автором темы, заключается в том, что даже если основная таблица пуста, в таблице границ может висеть запись. Выясним причину: встроенный язык 1С спроектирован так, что граница должна существовать всегда, если хотя бы раз была установлена. Платформа воспринимает границу как «указатель», который может перемещаться, но не исчезать.
Разберем поведение кода, который обычно пытаются использовать программисты:
МоментВремениДокумента = Новый МоментВремени('00010101000000');
Отбор = Новый Структура("Организация", ВыбОрганизация);
Последовательности.ПартионныйУчетБУ.УстановитьГраницу(МоментВремениДокумента, Отбор);
При выполнении данного кода платформа выполняет операцию UPSERT (Update или Insert). Если записи для данной организации еще не было, она будет создана с пустой датой. Если она была — она будет обновлена. Но команда DELETE (удаление строки) в этот момент не вызывается. С точки зрения 1С, граница на 01.01.0001 — это просто «сброшенная» граница, но строка в таблице базы данных физически остается.
Если нам критически важно, чтобы запись исчезла физически (например, для корректной работы внешних систем интеграции или сложных отчетов на СКД, которые некорректно обрабатывают пустые даты), придется обратиться к средствам СУБД. Это единственный надежный способ физической очистки таблицы границ.
Проанализируем шаги, необходимые для выполнения этой операции:
_SeqBnd. Чтобы узнать точное имя таблицы для последовательности ПартионныйУчетБУ, используем встроенную функцию:
СтруктураТаблиц = ПолучитьСтруктуруХраненияБазыДанных();
// Ищем в структуре таблицу, относящуюся к нашей последовательности
_SeqBnd123) определено, необходимо выполнить команду удаления. Внимание: всегда делайте бэкап перед прямым вмешательством в БД!
DELETE FROM _SeqBnd123 WHERE _Fld456 = @P1 -- где _Fld456 - ID измерения (например, Организации)
ОбновитьПовторноИспользуемыеЗначения().Рассмотрим ситуацию, когда нам нужно не просто удалить границу, а очистить всю последовательность. Метод Очистить() работает только с основной таблицей регистраций. Чтобы «синхронизировать» состояние, часто применяют следующую последовательность действий:
// 1. Очищаем регистрации документов
Последовательности.ПартионныйУчетБУ.Очистить(Отбор);
// 2. Устанавливаем границу в начало времен
ПустойМомент = Новый МоментВремени('00010101000000');
Последовательности.ПартионныйУчетБУ.УстановитьГраницу(ПустойМомент, Отбор);
Хотя это не удаляет строку физически, это приводит систему в логически чистое состояние, которое является штатным для 1С.
Если задача стоит глобально — очистить все границы последовательности во всей базе — мы можем воспользоваться инструментами тестирования и исправления (ТиИ).
_SeqBnd и их физической очистке. Однако помните, что это действие требует монопольного доступа и приведет к потере всех текущих границ для всех пользователей.Посмотрим на ситуацию со стороны архитектуры данных. Зачастую разработчики хотят удалить границу, потому что в ней фигурирует объект (например, Организация), который уже помечен на удаление или удален из базы. Важный момент: если объект физически удален из справочника, но запись в таблице границ осталась, она превращается в «Объект не найден». Такие записи игнорируются большинством типовых алгоритмов проведения, но продолжают отображаться в консоли запросов.
В этом случае эффективнее всего использовать SQL-метод, описанный выше, так как штатные средства УстановитьГраницу() могут выдавать ошибку при попытке передать в отбор «битую» ссылку.
Мы выяснили, что в рамках встроенного языка 1С нет прямого метода для выполнения команды DELETE в таблице границ последовательности. Платформа предполагает, что граница — это константа состояния, которая может быть только изменена.
Для решения задачи мы рекомендуем:
УстановитьГраницу() на пустую дату, если физическое наличие строки не мешает логике ваших отчетов.Таким образом, понимание внутреннего устройства таблиц _SeqBnd позволяет эффективно управлять состоянием системы даже в условиях ограничений платформенных методов.