Как правильно написать прямой SQL-запрос к регистру 1С 7.7 с фильтром по реквизиту справочника

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

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

Разбор ошибки Meta name parser error

Проанализируем ситуацию, когда разработчик пытается выполнить запрос к виртуальной таблице $РегистрОстатки.ОперСклады и наложить условие на реквизит справочника "МестаХранения". Типичная ошибка выглядит так: Meta name parser error: неизвестное метаимя или алиас "$Скл". Выясним причину этой ошибки.

В SQL-базе данных 1С 7.7 таблица регистра остатков содержит только идентификаторы (ID) элементов справочников. Она не содержит полей (реквизитов) этих справочников. Когда вы пишете в условии WHERE $Скл.РазрешенаОтгрузка = :ВыбСклад, препроцессор 1С++ не понимает, откуда взять таблицу $Скл, так как в секции FROM указан только регистр. Для SQL-сервера это выглядит так, будто вы пытаетесь обратиться к столбцу несуществующей таблицы.

Шаг 1: Правильное соединение таблиц через JOIN

Чтобы получить доступ к реквизитам справочника, нам необходимо соединить таблицу остатков регистра с таблицей самого справочника. Рассмотрим, как это сделать структурно. Мы будем использовать конструкцию INNER JOIN, которая объединит только те записи, для которых найдены соответствия в обеих таблицах.

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


|FROM  
|    $РегистрОстатки.ОперСклады as Рег
|INNER JOIN
|    $Справочник.МестаХранения as Скл ON Рег.Склад = Скл.id

В этом фрагменте мы указываем SQL-серверу: "Возьми таблицу остатков (алиас Рег) и соедини её с таблицей справочника МестаХранения (алиас Скл) по правилу: значение в поле Склад регистра должно совпадать с уникальным идентификатором ID в справочнике". Только после такого соединения нам станут доступны реквизиты справочника Склад для фильтрации в секции WHERE.

Шаг 2: Работа с перечислениями в параметрах

В 1С 7.7 перечисления хранятся в базе данных как специфические строковые идентификаторы. Напрямую сравнивать их в запросе с привычными "Да" или "Нет" нельзя. Однако компонента 1С++ предоставляет удобный метод УстановитьТекстовыйПараметр, который автоматически преобразует объект 1С в понятный для SQL вид.

Рассмотрим пример установки параметра для системного перечисления Булево:


RS = СоздатьОбъект("ODBCRecordset");
RS.УстановитьТекстовыйПараметр("флОтгрузка", Перечисление.Булево.Да);

Важно помнить, что в самом тексте запроса перед именем параметра ставится двоеточие: :флОтгрузка. Препроцессор сам подставит нужный внутренний идентификатор (ID перечисления) вместо этого маркера.

Шаг 3: Полный текст решения с типизацией результата

Для того чтобы 1С понимала, что возвращаемые SQL-сервером строки — это не просто наборы символов, а объекты 1С (элементы справочников), мы используем специальную типизацию в секции SELECT. Посмотрим на итоговый пример кода:


ТекстЗапроса = " 
|SELECT
|    Рег.Товар as [Тов $Справочник.ТМЦ],
|    Рег.Склад as [Скл $Справочник.МестаХранения],
|    Рег.КолЕдИзм1Остаток as Кол
|FROM  
|    $РегистрОстатки.ОперСклады as Рег
|INNER JOIN
|    $Справочник.МестаХранения as Скл ON Рег.Склад = Скл.id
|WHERE
|    $Скл.РазрешенаОтгрузка = :флОтгрузка
|";

RS.УстановитьТекстовыйПараметр("флОтгрузка", Перечисление.Булево.Да);
ТЗ = RS.ВыполнитьИнструкцию(ТекстЗапроса);

Обратите внимание на конструкцию [Тов $Справочник.ТМЦ]. Это указание препроцессору 1С++, что поле Товар нужно преобразовать в объект типа Справочник.ТМЦ при загрузке результата в Таблицу Значений. Без этого вы получите в таблице только внутренние идентификаторы (строки типа " 1ZQ ").

Шаг 4: Оптимизация и "внутренние" фильтры

Разберем ситуацию более глубоко. В прямых запросах к 1С++ существует возможность накладывать фильтры прямо в макросе виртуальной таблицы. Это работает быстрее, чем фильтрация через WHERE, так как SQL-сервер будет обсчитывать остатки только по тем данным, которые прошли первичный фильтр.

Сравним два подхода:

  1. Внешний фильтр (WHERE): Сначала SQL считает остатки по всем складам и всем товарам, а потом отсеивает лишние. Это ресурсоемко.
  2. Внутренний фильтр (через параметры макроса): SQL выбирает движения только по нужным критериям и сразу считает итог.

Однако, если условие накладывается на реквизит справочника (как в нашем случае — РазрешенаОтгрузка), такой фильтр нельзя просто так засунуть внутрь макроса регистра, так как реквизита нет в таблице итогов регистра. В этом случае INNER JOIN — единственный верный путь.

Дополнительные рекомендации по производительности

Проанализируем еще несколько важных моментов, которые помогут ускорить работу ваших прямых запросов:

1. Использование NOLOCK. В среде 1С 7.7 крайне важно не блокировать таблицы во время чтения. Рекомендуется добавлять указание (NOLOCK) после каждой таблицы в секции FROM и JOIN. Это позволит выполнять запрос, не дожидаясь окончания транзакций записи других пользователей.

2. Проблема пустых значений. Помните, что в SQL 1С 7.7 пустая ссылка — это не NULL и не пустая строка "". Это строка, заполненная пробелами (обычно 9 или 13 штук). Чтобы корректно проверить на пустоту, используйте передачу пустого значения через параметр: RS.УстановитьТекстовыйПараметр("ПустойТовар", ПолучитьПустоеЗначение("Справочник.ТМЦ")).

3. Индексы. Проверьте, стоит ли в конфигураторе галочка "Сортировка" у того реквизита, по которому вы делаете отбор (в нашем примере — РазрешенаОтгрузка). Если галочки нет, SQL-серверу придется каждый раз сканировать всю таблицу справочника складов, что на больших справочниках приведет к значительным задержкам.

Таким образом, мы выяснили, что ключ к успеху в прямых запросах 1С 7.7 — это четкое понимание структуры хранения данных в SQL и умелое использование механизмов соединения таблиц и типизации результатов, предоставляемых компонентой 1С++.

← На главную