Как исправить ошибку «Meta name parser error: виртуальное поле не найдено» в прямом запросе 1С 7.7

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

При выполнении прямых SQL-запросов в 1С 7.7 с использованием внешней компоненты 1С++ разработчики часто сталкиваются с ошибкой синтаксического анализатора метаданных: «Meta name parser error: виртуальное поле не найдено». В этой статье мы разберем причины возникновения данной ошибки при работе с макросом $ПоследнееЗначение, рассмотрим правильный синтаксис его вызова и изучим альтернативный способ получения данных из таблицы периодических реквизитов _1SCONST.

Причина ошибки парсера метаданных 1С++

Проанализируем исходный запрос, в котором возникла ошибка. Разработчик пытается получить последнее значение периодического реквизита «СерийныйНомер» для справочника «ДСП_Аппараты»:


SELECT   
    СпрАпп.ID КАК Ссылка,
    $ПоследнееЗначение.СпрАпп.СерийныйНомер(СпрАпп.ТекЭлемент, ТекДата, 86399000) КАК СерийныйНомер
FROM
    $Справочник.ДСП_Аппараты КАК СпрАпп
WHERE
    СерийныйНомер = СерийникДляПоиска

Причина сбоя заключается в том, как парсер 1С++ (модуль MetaNameParser) обрабатывает макрос $ПоследнееЗначение. Данный макрос ожидает в качестве имени объекта метаданных строгое наименование справочника из конфигуратора, а не псевдоним таблицы (алиас), заданный в секции FROM.

Когда парсер видит конструкцию $ПоследнееЗначение.СпрАпп.СерийныйНомер, он ищет объект метаданных с именем СпрАпп. Поскольку такого объекта в конфигурации нет (это всего лишь псевдоним для таблицы $Справочник.ДСП_Аппараты), парсер выдает ошибку о том, что виртуальное поле не найдено.

Решение 1. Исправление синтаксиса макроса $ПоследнееЗначение

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

$ПоследнееЗначение.<ВидОбъекта>.<Идентификатор>(Элемент, Дата)

Для исправления ошибки заменим псевдоним таблицы СпрАпп на реальное имя вида справочника из метаданных — ДСП_Аппараты. Также передадим параметры даты и искомого значения через текстовые параметры объекта ODBCRecordSet.

Исправленный вариант прямого запроса выглядит следующим образом:


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

// Задаем текст SQL-запроса с правильным макросом
ТекстЗапроса = "
|SELECT   
|    СпрАпп.ID КАК [Ссылка $Справочник.ДСП_Аппараты], 
|    $ПоследнееЗначение.ДСП_Аппараты.СерийныйНомер(СпрАпп.ID, :ТекДата) КАК СерийныйНомер 
|FROM 
|    $Справочник.ДСП_Аппараты КАК СпрАпп 
|WHERE 
|    $ПоследнееЗначение.ДСП_Аппараты.СерийныйНомер(СпрАпп.ID, :ТекДата) = :СерийникДляПоиска
|";

// Устанавливаем параметры
Запрос.УстановитьТекстовыйПараметр("СерийникДляПоиска", СокрЛП(СерийникДляПоиска));
Запрос.УстановитьТекстовыйПараметр("ТекДата", ТекущаяДата());

// Выполняем запрос
Результат = Запрос.ВыполнитьИнструкцию(ТекстЗапроса);

Важное примечание: Обратите внимание, что псевдоним вычисляемого поля из секции SELECT нельзя использовать напрямую в условии WHERE на уровне T-SQL. По этой причине выражение макроса дублируется в секции фильтрации или оборачивается во вложенный запрос.

Решение 2. Прямой запрос к системной таблице _1SCONST

Выясним, как данные периодических реквизитов хранятся в базе данных 1С 7.7. Все периодические реквизиты справочников и периодические константы находятся в единой системной таблице _1SCONST.

Основные поля таблицы _1SCONST:

  1. OBJID — идентификатор объекта справочника, к которому относится значение.
  2. ID — внутренний идентификатор реквизита в метаданных.
  3. DATE — дата установки значения.
  4. VALUE — значение реквизита в строковом формате.

Мы можем написать прямой запрос к таблице _1SCONST через объект ODBCRecordSet и вспомогательный объект MetaDataWork для получения ID реквизита.

Разберем пример кода:


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

// Передаем дату и ID реквизита справочника
рс.УстановитьТекстовыйПараметр("ТекДата", ТекущаяДата());
рс.УстановитьТекстовыйПараметр("ИДРеквизита", Мета.ИДРеквизитаСправочника("ДСП_Аппараты", "СерийныйНомер"));
рс.УстановитьТекстовыйПараметр("НужныйСерийник", СокрЛП(СерийникДляПоиска));

// Запрос с типизацией возвращаемого значения
ТекстЗапроса = "
|SELECT TOP 10 
|    Константы.OBJID [Объект $Справочник.ДСП_Аппараты],
|    Константы.VALUE [Значение $Строка]
|FROM 
|    _1SCONST AS Константы WITH (NOLOCK)
|WHERE 1=1
|    AND Константы.DATE <= :ТекДата
|    AND Константы.ID = :ИДРеквизита
|    AND Константы.VALUE = :НужныйСерийник
|ORDER BY 
|    Константы.DATE DESC
|";

ТЗ = рс.ВыполнитьИнструкцию(ТекстЗапроса);

Особенности типизации полей в 1С++

По умолчанию при обращении к полю OBJID или VALUE таблицы _1SCONST SQL Server возвращает внутренние символьные идентификаторы 1С (например, 3TF4). Для того чтобы 1С++ автоматически преобразовала эти идентификаторы в объекты 1С (ссылки на справочники или документы), необходимо применить специальную типизацию полей в квадратных скобках:

  1. Константы.OBJID [Объект $Справочник.ДСП_Аппараты] — приводит внутренний ID к ссылке на справочник «ДСП_Аппараты».
  2. Константы.VALUE [Значение $Перечисление.ВидыОпераций] — если значением периодического реквизита является ссылка на перечисление или другой справочник.

Использование явной типизации гарантирует получение готовых объектов 1С в результатах выполнения запроса вместо сырых идентификаторов базы данных.

← На главную