При организации интеграции между базами данных 1С с использованием COM-соединения разработчики нередко сталкиваются с ошибками синтаксического анализа запроса. Типичными симптомами являются сообщения вида «Неверные параметры "Документ.ЗаказПоставщику.ПустаяСсылка"» или «Поле не найдено "ПоступлениеТоваровУслуг.ЗаказПоставщику"», несмотря на то, что в структуре целевой информационной базы указанные объекты и реквизиты точно существуют. Разберем по шагам, почему возникают такие ситуации, как выявить скрытые логические ошибки при инициализации объектов и как правильно организовать фильтрацию по пустым ссылкам во внешних базах.
Проанализируем наиболее распространенную и сложно уловимую при отладке ошибку. Разработчик создает объект запроса во внешней базе через COM-соединение, но затем механически дублирует строку создания запроса стандартным локальным оператором:
// Создание COM-объекта в удаленной базе
Запрос = Ком.NewObject("Запрос");
// Случайная перезапись переменной локальным объектом
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("Дата1", НачалоДня(ДатаС));
Запрос.УстановитьПараметр("Дата2", КонецДня(ДатаПо));
В приведенном примере вторая строка Запрос = Новый Запрос; полностью перетирает ссылку на удаленный запрос Ком.NewObject("Запрос"). В результате последующий вызов метода Выполнить() происходит не в удаленной базе-приемнике, а в текущей базе-источнике. Если в текущей конфигурации нет документа ЗаказПоставщику или у документа ПоступлениеТоваровУслуг отсутствует данный реквизит, платформа выдаст ошибку отсутствия метаданных или неверного значения функции ЗНАЧЕНИЕ(...).
Для исправления ситуации необходимо убрать лишнюю локальную инициализацию и передавать параметры строго в объект удаленной базы:
// Корректная инициализация запроса в контексте внешней базы
Запрос = Ком.NewObject("Запрос");
Запрос.Текст =
"ВЫБРАТЬ
| Поступление.Ссылка,
| Поступление.Организация,
| Поступление.Контрагент
|ИЗ
| Документ.ПоступлениеТоваровУслуг КАК Поступление
|ГДЕ
| Поступление.Дата МЕЖДУ &Дата1 И &Дата2
| И НЕ Поступление.ЗаказПоставщику = ЗНАЧЕНИЕ(Документ.ЗаказПоставщику.ПустаяСсылка)";
Запрос.УстановитьПараметр("Дата1", НачалоДня(ДатаС));
Запрос.УстановитьПараметр("Дата2", КонецДня(ДатаПо));
РезультатЗапроса = Запрос.Выполнить();
В ряде сценариев конструкция ЗНАЧЕНИЕ(...) внутри текста запроса может быть нежелательна, особенно если тип метаданных динамически подставляется или реквизит является составным. В этом случае пустую ссылку можно передать в качестве параметра. Посмотрим, как корректно получить пустую ссылку из внешнего соединения:
ПустаяСсылка() должен вызываться именно у менеджера внешней базы.Рассмотрим пример кода:
// Получаем пустую ссылку из целевой конфигурации
ПустаяСсылкаЗаказ = Ком.Документы.ЗаказПоставщику.ПустаяСсылка();
Запрос = Ком.NewObject("Запрос");
Запрос.Текст =
"ВЫБРАТЬ
| Поступление.Ссылка КАК Ссылка
|ИЗ
| Документ.ПоступлениеТоваровУслуг КАК Поступление
|ГДЕ
| НЕ Поступление.ЗаказПоставщику = &ПустаяСсылка";
Запрос.УстановитьПараметр("ПустаяСсылка", ПустаяСсылкаЗаказ);
Результат = Запрос.Выполнить().Выгрузить();
Важно помнить: нельзя передавать в COM-запрос пустую ссылку, полученную в локальной базе через Документы.ЗаказПоставщику.ПустаяСсылка(). Объекты ссылочных типов принадлежат конкретному пространству информационной базы и не могут быть сопоставлены СУБД удаленной базы напрямую.
Если реквизит шапки или табличной части имеет составной тип (например, ссылается на несколько разных типов документов заказов), простая проверка НЕ Поле = ЗНАЧЕНИЕ(...) может сработать некорректно. В незаполненном поле составного типа может храниться системное значение Неопределено либо пустая ссылка другого вида документа.
Разберем способы корректной фильтрации таких полей:
Используем предикат ССЫЛКА совместно с проверкой на неравенство пустой ссылке нужного вида документа:
ГДЕ
Поступление.ЗаказПоставщику ССЫЛКА Документ.ЗаказПоставщику
И НЕ Поступление.ЗаказПоставщику = ЗНАЧЕНИЕ(Документ.ЗаказПоставщику.ПустаяСсылка)
ВЫРАЗИТЬ:
Для оптимизации обращения к реквизиту составного типа приведем его к конкретному типу метаданных с помощью функции ВЫРАЗИТЬ. Это исключает неявные соединения с таблицами других документов, входящих в составной тип:
ГДЕ
НЕ ВЫРАЗИТЬ(Поступление.ЗаказПоставщику КАК Документ.ЗаказПоставщику) = ЗНАЧЕНИЕ(Документ.ЗаказПоставщику.ПустаяСсылка)
И НЕ Поступление.ЗаказПоставщику ЕСТЬ NULL
Если запрос продолжает выдавать ошибки структуры метаданных при подключении через V83.COMConnector, выполним следующие контрольные шаги:
Srvr и Ref (или File) указывают именно на внешнюю информационную базу, а не на текущую базу данных.