Почему не работает оператор ССЫЛКА в запросе 1С и как исправить ошибку?

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

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

Причина 1. Проверяемый тип отсутствует в составе реквизита

Проанализируем типовую ситуацию: в документе (например, РасходнаяНакладная в конфигурации 1С:Управление нашей фирмой) есть составной реквизит ДокументОснование, и мы пытаемся выполнить следующий отбор:


ГДЕ
    РасходнаяНакладная.ДокументОснование ССЫЛКА Документ.ЗаказПокупателя

В этом случае платформа выдает ошибку о несовместимости типов. Дело в том, что оператор ССЫЛКА строго контролирует метаданные конфигурации. Если тип Документ.ЗаказПокупателя не включен в список допустимых типов реквизита ДокументОснование на этапе конфигурирования, компилятор запросов сочтет такое выражение заведомо ошибочным.

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

  1. Откроем дерево метаданных в конфигураторе и найдем исследуемый документ.
  2. Раскроем состав его реквизитов и выделим поле ДокументОснование.
  3. В палитре свойств откроем свойство Тип и изучим составной тип данных.
  4. Если нужного документа нет в списке, проверим соседние реквизиты. Например, в типовых конфигурациях (в частности, в 1С:УНФ) ссылка на Документ.ЗаказПокупателя вынесена в специализированный отдельный реквизит Заказ, а не в ДокументОснование.

Если мы обратимся к корректному полю, запрос отработает без ошибок:


ВЫБРАТЬ
    РасходнаяНакладная.Ссылка КАК Ссылка
ИЗ
    Документ.РасходнаяНакладная КАК РасходнаяНакладная
ГДЕ
    РасходнаяНакладная.Заказ ССЫЛКА Документ.ЗаказПокупателя

Причина 2. Нарушение правил синтаксиса оператора ССЫЛКА

Рассмотрим правила написания оператора ССЫЛКА, несоблюдение которых приводит к синтаксическим ошибкам:

  1. Имя таблицы в единственном числе. Правый операнд требует строгого указания класса объекта метаданных в единственном числе: Документ.ЗаказПокупателя или Справочник.Контрагенты. Попытки написать Документы.ЗаказПокупателя или ДокументСсылка.ЗаказПокупателя приведут к синтаксической ошибке.
  2. Отрицание выносится в начало. В языке запросов 1С отсутствует оператор вида НЕ ССЫЛКА. Конструкция Поле НЕ ССЫЛКА Документ.ЗаказПокупателя вызовет ошибку. Корректное написание требует вынесения логического отрицания: НЕ Поле ССЫЛКА Документ.ЗаказПокупателя или НЕ (Поле ССЫЛКА Документ.ЗаказПокупателя).
  3. Невозможность параметризации. Правый операнд оператора ССЫЛКА является литералом схемы метаданных. Нельзя написать Поле ССЫЛКА &НужныйТип.

Альтернативные варианты проверки типа в запросе

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

Вариант 1. Использование функции ТИПЗНАЧЕНИЯ

Функция ТИПЗНАЧЕНИЯ возвращает тип переданного выражения. Ее можно сравнивать с литералом ТИП(...) либо передавать тип через параметр запроса, что особенно удобно при динамическом построении условий:


ВЫБРАТЬ
    РасходнаяНакладная.Ссылка КАК Ссылка
ИЗ
    Документ.РасходнаяНакладная КАК РасходнаяНакладная
ГДЕ
    ТИПЗНАЧЕНИЯ(РасходнаяНакладная.ДокументОснование) = ТИП(Документ.ЗаказПокупателя)

Если требуется передать тип динамически из встроенного языка, передадим параметр в запрос:

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

А в тексте запроса укажем условие:


ГДЕ
    ТИПЗНАЧЕНИЯ(РасходнаяНакладная.ДокументОснование) = &ИскомыйТип

Вариант 2. Фильтрация через оператор ВЫРАЗИТЬ

Оператор ВЫРАЗИТЬ сужает составной тип поля до конкретного типа. Если фактическое значение в строке базы данных не соответствует указанному типу, функция возвращает значение NULL. Это позволяет отбирать записи следующим образом:


ВЫБРАТЬ
    РасходнаяНакладная.Ссылка КАК Ссылка
ИЗ
    Документ.РасходнаяНакладная КАК РасходнаяНакладная
ГДЕ
    ВЫРАЗИТЬ(РасходнаяНакладная.ДокументОснование КАК Документ.ЗаказПокупателя) ЕСТЬ НЕ NULL

Важный нюанс производительности: отбор через ССЫЛКА фильтрует строки, но при последующем обращении через точку к реквизитам составного поля (например, РасходнаяНакладная.ДокументОснование.Номер) СУБД построит неявные соединения LEFT JOIN со всеми возможными таблицами составного типа. Чтобы избежать падения производительности, всегда используем ВЫРАЗИТЬ при разыменовании полей составного типа:


ВЫБРАТЬ
    ВЫРАЗИТЬ(РасходнаяНакладная.ДокументОснование КАК Документ.ЗаказПокупателя).Номер КАК НомерЗаказа
ИЗ
    Документ.РасходнаяНакладная КАК РасходнаяНакладная
ГДЕ
    РасходнаяНакладная.ДокументОснование ССЫЛКА Документ.ЗаказПокупателя

Таким образом, для устранения ошибки в первую очередь проверяем состав типов реквизита в конфигураторе, корректность обращения к имени реквизита, а также строгое соблюдение правил синтаксиса оператора ССЫЛКА.

← На главную