Почему возникает «Ошибка в индексном выражении» при выполнении запроса в 1С 7.7 и как её исправить?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

При разработке и сопровождении конфигураций на платформе 1С:Предприятие 7.7 разработчики периодически сталкиваются с ситуацией, когда при выполнении штатного «черного» запроса к регистру возникает исключительная ситуация: «Ошибка в индексном выражении». При этом ошибка может проявляться не постоянно, а лишь периодически, нарушая штатную работу пользователей.

Разберем детально механизм возникновения этой проблемы в файловой версии 1С 7.7, выясним ее технические предпосылки и рассмотрим эффективные способы устранения сбоя.

Причины возникновения ошибки

Рассмотрим структуру типового запроса, в котором проявляется проблема:


глТекстЗапроса = "
|Период с ДатаН По ДатаК; Без итогов;
|Заказ        = Регистр.Заказы.Заказ;
|Номенклатура = Регистр.Заказы.Номенклатура;
|КолЗаказано  = Регистр.Заказы.Заказано;
|КолПринято   = Регистр.Заказы.Принято;
|Функция Заказано  = Сумма(КолЗаказано);
|Функция НеПринято = Сумма(КолЗаказано-КолПринято);
|Группировка Номенклатура Без Групп;
|Условие(Заказ = ВыбЗаказ);
|Условие(Номенклатура = ВыбНоменклатура);
|";
Запрос.Выполнить(глТекстЗапроса);

Проанализируем техническую сторону выполнения такого кода:

  1. Неопределенный вид реквизита или измерения. Если измерение регистра Заказ имеет общий тип Документ (без указания конкретного вида), в таблицах формата DBF оно хранится в виде 13-символьной строки: 4 символа занимает идентификатор вида документа в 36-ричной системе счисления, а оставшиеся 9 символов — уникальный идентификатор конкретного документа. Если в условие Условие(Заказ = ВыбЗаказ) передается неинициализированная переменная, значение другого типа (число, строка, нетипизированное пустое значение), движок базы данных CodeBase не может составить корректное индексное выражение для временной таблицы, что приводит к фатальному сбою.
  2. Построение временных индексных файлов (CDX). При выполнении штатного объекта Запрос платформа 1С 7.7 динамически создает во временном каталоге операционной системы (папка %TEMP%) временные таблицы DBF и соответствующие им индексы CDX. Если пути содержат длинные имена, спецсимволы, кириллицу или возникают коллизии блокировок при одновременном обращении нескольких процессов, попытка построения индекса завершается ошибкой.
  3. Повреждение физических индексов базы данных. Поврежденные индексные файлы таблиц итогов (RGxxxx.cdx) или движений регистров (RAxxxx.cdx) вызывают сбой при обращении к измерениям, для которых включен отбор итогов или движений.

Важное замечание: конструкция Попытка ... Исключение в платформе 1С 7.7 не способна перехватить критические ошибки ядра базы данных CodeBase, поэтому обернуть Запрос.Выполнить() в блок перехвата для скрытия сбоя не удастся — работа модуля будет прервана платформой.

Способ 1. Проверка типов и явная фильтрация по виду документа

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

Посмотрим на пример фильтрации по виду документа внутри текста запроса:


глТекстЗапроса = "
|Период с ДатаН По ДатаК; Без итогов;
|Заказ        = Регистр.Заказы.Заказ;
|Номенклатура = Регистр.Заказы.Номенклатура;
|КолЗаказано  = Регистр.Заказы.Заказано;
|КолПринято   = Регистр.Заказы.Принято;
|Функция Заказано  = Сумма(КолЗаказано);
|Функция НеПринято = Сумма(КолЗаказано-КолПринято);
|Группировка Номенклатура Без Групп;
|Условие(Найти(""ЗаказНаОтгрузку/ЗаказНаПриемку/"", Заказ.Вид() + ""/"") > 0);
|Условие(Заказ = ВыбЗаказ);
|Условие(Номенклатура = ВыбНоменклатура);
|";

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


Если (ТипЗначенияСтр(ВыбЗаказ) <> "Документ") Или (ПустоеЗначение(ВыбЗаказ) = 1) Тогда
    // Прерываем выполнение до вызова метода Выполнить()
    Возврат 0;
КонецЕсли;

Если (ТипЗначенияСтр(ВыбНоменклатура) <> "Справочник") Или (ПустоеЗначение(ВыбНоменклатура) = 1) Тогда
    Возврат 0;
КонецЕсли;

Если глЗапрос.Выполнить(глТекстЗапроса) = 0 Тогда
    Возврат 0;
КонецЕсли;

Способ 2. Полное пересоздание индексных файлов базы данных

Штатная операция переиндексации при запуске конфигуратора не всегда исправляет логически поврежденную внутреннюю структуру файлов CDX. Для гарантированного восстановления индексов выполним следующие действия:

  1. Завершим работу всех пользователей и служб, работающих с базой данных 1С.
  2. Создадим полную резервную копию каталога информационной базы.
  3. В каталоге информационной базы найдем и удалим все файлы с расширением .CDX (таблицы данных .DBF не трогаем).
  4. Запустим 1С:Предприятие в монопольном режиме (или откроем Конфигуратор) и подтвердим автоматическое создание новых индексных файлов.
  5. В меню Конфигуратора выполним операцию «Администрирование» -> «Тестирование и исправление ИБ», обязательно отметив пункты «Проверка физической целостности», «Проверка ссылочной целостности» и «Пересчет итогов».

Способ 3. Переход на прямую выборку через объект «Регистр»

Когда требуется быстро получить движения или остатки по конкретному набору измерений (в данном случае по известному заказу и номенклатуре), использование тяжелого объекта Запрос избыточно. Обращение через штатный объект Регистр работает быстрее и не создает временных DBF/CDX файлов в папке Temp.

Рассмотрим альтернативную реализацию через объектную модель:


Рег = СоздатьОбъект("Регистр.Заказы");

// Если в метаданных включен отбор движений по измерению
Рег.УстановитьЗначениеФильтра("Заказ", ВыбЗаказ);
Рег.УстановитьЗначениеФильтра("Номенклатура", ВыбНоменклатура);

ИтогЗаказано = 0;
ИтогНеПринято = 0;

Рег.ВыбратьДвижения(ДатаН, ДатаК);
Пока Рег.ПолучитьДвижение() = 1 Цикл
    Если (Рег.Заказ = ВыбЗаказ) И (Рег.Номенклатура = ВыбНоменклатура) Тогда
        ИтогЗаказано = ИтогЗаказано + Рег.Заказано;
        ИтогНеПринято = ИтогНеПринято + (Рег.Заказано - Рег.Принято);
    КонецЕсли;
КонецЦикла;

Способ 4. Проверка системных настроек каталога временных файлов

Поскольку генератор запросов 1С 7.7 активно использует системные переменные среды, проверим настройки путей на рабочем месте или сервере терминалов:

  1. Откроем свойства системы и перейдем в раздел «Переменные среды».
  2. Проверим значения переменных TEMP и TMP для пользователя и системы.
  3. Зададим простой и короткий путь без пробелов и русских букв, например C:\Temp.
  4. Убедимся, что у пользователя 1С есть полные права на чтение, запись и удаление файлов в этом каталоге.
← На главную