Как исправить ошибку «Временная таблица уже существует "ВременнаяТаблицаРешений"» при закрытии месяца в 1С

Программист 1С v8.3 (Управляемые формы) 1С:Управление нашей фирмой Управленческий учет IT и автоматизация бизнеса
← На главную

При выполнении регламентной операции «Закрытие месяца» (или расчете себестоимости запасов) в конфигурациях 1С (таких как «Управление нашей фирмой», «ERP Управление предприятием» или «Комплексная автоматизация») пользователи и разработчики часто сталкиваются с аппаратными и логическими сбоями. Один из самых неочевидных сбоев — это ошибка СУБД, сообщающая о повторном создании уже существующей временной таблицы.

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

Механизм возникновения ошибки: почему «зависает» временная таблица?

Для того чтобы понять природу этой ошибки, нам необходимо заглянуть внутрь программного кода проведения документа ЗакрытиеМесяца. В модуле объекта этого документа (или в общих модулях расчета себестоимости) выполняется расчет фактической стоимости списания запасов. Этот расчет производится итерационным методом путем решения системы линейных уравнений (СЛУ) в специальном цикле.

Давайте проанализируем текст запроса, который выполняется на каждой итерации этого цикла:


ВЫБРАТЬ
    УзлыКорректировкиСтоимостиСписания.НомерУзла КАК НомерУзла,
    СУММА(ВЫРАЗИТЬ(ВЫБОР
                КОГДА УзлыКорректировкиСтоимостиСписания.Количество <> 0
                    ТОГДА ТаблицаРешений.Сумма * ВЫБОР
                            КОГДА УчетЗатрат.Количество = 0
                                ТАКЖЕ УчетЗатрат.Сумма
                            ИНАЧЕ УчетЗатрат.Количество
                        КОНЕЦ / УзлыКорректировкиСтоимостиСписания.Количество
                ИНАЧЕ 0
            КОНЕЦ КАК ЧИСЛО(23, 10))) КАК Сумма
ПОМЕСТИТЬ ВременнаяТаблицаРешений
ИЗ
    РегистрСведений.УзлыКорректировкиСтоимостиСписания КАК УзлыКорректировкиСтоимостиСписания
    ЛЕВОЕ СОЕДИНЕНИЕ УчетЗатрат КАК УчетЗатрат
        ЛЕВОЕ СОЕДИНЕНИЕ ТаблицаРешений КАК ТаблицаРешений
        ПО УчетЗатрат.НомерУзла = ТаблицаРешений.НомерУзла
    ПО УзлыКорректировкиСтоимостиСписания.Организация = УчетЗатрат.Организация
        И УзлыКорректировкиСтоимостиСписания.СтруктурнаяЕдиница = УчетЗатрат.СтруктурнаяЕдиница
        И УзлыКорректировкиСтоимостиСписания.СчетУчета = УчетЗатрат.СчетУчета
        И УзлыКорректировкиСтоимостиСписания.Номенклатура = УчетЗатрат.Номенклатура
        И УзлыКорректировкиСтоимостиСписания.Характеристика = УчетЗатрат.Характеристика
        И УзлыКорректировкиСтоимостиСписания.Партия = УчетЗатрат.Партия
        И УзлыКорректировкиСтоимостиСписания.ЗаказПокупателя = УчетЗатрат.ЗаказПокупателя
ГДЕ
    УзлыКорректировкиСтоимостиСписания.Регистратор = &Регистратор

СГРУППИРОВАТЬ ПО
    УзлыКорректировкиСтоимостиСписания.НомерУзла

ИНДЕКСИРОВАТЬ ПО
    НомерУзла
;

В нормальном режиме работы СЛУ рассчитывает точные суммы списания за несколько итераций. Погрешность (отклонение) с каждым шагом цикла стремится к нулю. Когда точность расчетов достигает заданного порога, цикл завершается, временная таблица ВременнаяТаблицаРешений явно уничтожается в конце итерации с помощью команды УНИЧТОЖИТЬ, а полученные данные записываются в регистры.

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

  1. Вместо уменьшения погрешности, значения сумм на каждой новой итерации начинают лавинообразно увеличиваться (происходит экспоненциальный рост в геометрической прогрессии).
  2. Примерно к 15–30 итерации числа в колонке Сумма достигают гигантских размеров (сотни триллионов).
  3. При попытке СУБД выполнить приведение типов ВЫРАЗИТЬ(... КАК ЧИСЛО(23, 10)) происходит критическая ошибка базы данных — «Арифметическое переполнение при преобразовании numeric к типу данных numeric».
  4. Из-за этого аварийного завершения выполнение кода прерывается. Поток управления не доходит до инструкции уничтожения временной таблицы, но сам объект МенеджерВременныхТаблиц остается «живым» в контексте транзакции проведения документа.
  5. При повторной попытке проведения (или на следующем витке алгоритма внутри той же транзакции) система пытается снова создать таблицу с тем же именем: ПОМЕСТИТЬ ВременнаяТаблицаРешений. Платформа видит, что такая таблица уже зарегистрирована в менеджере, и выдает ошибку: Временная таблица уже существует "ВременнаяТаблицаРешений".

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

Рассмотрим подробнее, как быстро найти и локализовать эту ошибку в информационной базе.

Шаг 1. Поиск отрицательных остатков стандартными отчетами

Первое, что мы должны сделать — проверить наличие классических «минусов» по запасам на складах на конец закрываемого месяца. Для этого воспользуемся стандартными отчетами конфигурации.

  1. Откроем отчет «Движение товаров», «Остатки товаров» или «Анализ запасов».
  2. Установим период отчета, равный закрываемому месяцу.
  3. Обязательно настроим группировку по складам, номенклатуре, характеристикам и партиям (если ведется партионный учет).
  4. Выполним поиск строк, в которых конечный остаток по количеству имеет отрицательное значение.

Если такие позиции найдены, необходимо устранить отрицательные остатки. Это можно сделать путем корректировки последовательности проведения документов, исправления цепочки документов поступления и реализации, либо с помощью документа «Инвентаризация запасов» (ввод излишков/списание недостач).

Шаг 2. Анализ «суммовых» зависаний при положительном количестве

Бывают ситуации, когда количественный остаток по товару равен нулю или положителен, но при этом на складе «завис» отрицательный суммовой остаток. Такое происходит из-за ручных корректировок проводок, некорректного распределения дополнительных расходов или проведения документов «задним числом».

Для выявления таких аномалий проанализируем стоимостную оценку запасов:

Любой стоимостной минус без количества нарушает логику расчета распределения затрат и приводит к делению на сверхмалые величины, вызывая расходимость алгоритма СЛУ.

Шаг 3. Использование отладчика для точечной локализации проблемного товара

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

Рассмотрим по шагам, как локализовать проблемную номенклатуру:

  1. Откроем конфигурацию, найдем модуль объекта документа ЗакрытиеМесяца (или соответствующий общий модуль расчета себестоимости).
  2. Найдем процедуру, выполняющую расчет СЛУ (обычно она называется РешитьСЛУ или содержит итерационный цикл расчета стоимости списания).
  3. Установим точку останова внутри цикла перед вызовом метода Запрос.ВыполнитьПакет().
  4. Запустим проведение документа «Закрытие месяца» в режиме отладки.
  5. При остановке на точке отслеживаем переменную, отвечающую за текущее отклонение (например, ТекущееОтклонение или МаксимальноеОтклонение).
  6. Сделаем несколько шагов цикла (клавиша F8). Если мы видим, что значение отклонения лавинообразно увеличивается (например, с 10.5 перескакивает на 150 000, затем на 18 000 000 000 и так далее), значит, мы нашли проблемную итерацию.
  7. В окне «Табло» (Ctrl + Alt + W) вычислим следующее выражение:
    
    Запрос.МенеджерВременныхТаблиц.Таблицы.Найти("ТаблицаРешений").ПолучитьДанные().Выгрузить()
    
  8. В полученной таблице значений отсортируем колонку Сумма по убыванию. Мы сразу увидим строки с гигантскими нереалистичными суммами (например, -4.5168234E+18).
  9. Обратим внимание на колонку НомерУзла для этой строки. Это идентификатор связи.
  10. Теперь в табло выгрузим данные из таблицы УчетЗатрат (или регистра сведений УзлыКорректировкиСтоимостиСписания) по найденному номеру узла. В этой таблице будут четко указаны: Номенклатура, Характеристика, Склад и Партия, из-за которых расчет заходит в бесконечный цикл.

После того как конкретная номенклатурная позиция определена, вам останется лишь открыть ее карточку движения (отчет «Карточка движения товара») и устранить первопричину — некорректный документ, породивший отрицательный остаток.

Шаг 4. Временный обход ошибки переполнения (для диагностики)

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

Мы можем временно изменить конструкцию приведения типа в конфигураторе:

Вместо:

КОНЕЦ КАК ЧИСЛО(23, 10))) КАК Сумма

Пропишем:

КОНЕЦ КАК ЧИСЛО(38, 10))) КАК Сумма

Важное предупреждение: этот способ не решает проблему расхождения СЛУ! Он лишь предотвращает падение СУБД по ошибке переполнения разрядной сетки numeric. Это позволит алгоритму отработать все положенные итерации (обычно лимит составляет 50 или 100 итераций), после чего система аварийно завершит цикл по превышению лимита шагов и выдаст понятное текстовое сообщение в журнал регистрации с указанием конкретных проблемных узлов.

Выводы и профилактика

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

Используя предложенные нами методики анализа временных таблиц через отладчик, вы сможете локализовать и устранять подобные ошибки расчета себестоимости за считанные минуты.

← На главную