При написании запросов в системе «1С:Предприятие 8» разработчики часто сталкиваются с ситуацией, когда нужно отфильтровать данные по определенному типу документа или справочника в поле с составным типом. Казалось бы, оператор ССЫЛКА — это стандартный и наиболее производительный инструмент для этой задачи. Однако иногда попытка его использования приводит к ошибке «Несовместимые типы "ССЫЛКА"», в то время как аналогичная конструкция с ТИПЗНАЧЕНИЯ отрабатывает без проблем. Разберемся детально, почему так происходит, и как правильно проектировать запросы, чтобы избегать подобных коллизий. Для интерактивной проверки и отладки выражений запросов можно использовать консоль запросов для управляемых форм.
Рассмотрим практическую ситуацию. У нас есть регистр накопления РазмещениеЗаказовПокупателей, где измерение ЗаказПокупателя имеет составной тип данных. Мы хотим выбрать остатки только по тем записям, где заказом является Документ.ВнутреннийЗаказ. Проанализируем два варианта написания условия:
Вариант 1 (вызывает ошибку):
ВЫБРАТЬ
РазмещениеЗаказовПокупателейОстатки.ЗаказПокупателя КАК Заказ
ИЗ
РегистрНакопления.РазмещениеЗаказовПокупателей.Остатки КАК РазмещениеЗаказовПокупателейОстатки
ГДЕ
РазмещениеЗаказовПокупателейОстатки.ЗаказПокупателя ССЫЛКА Документ.ВнутреннийЗаказ
Вариант 2 (работает успешно):
ВЫБРАТЬ
РазмещениеЗаказовПокупателейОстатки.ЗаказПокупателя КАК Заказ
ИЗ
РегистрНакопления.РазмещениеЗаказовПокупателей.Остатки КАК РазмещениеЗаказовПокупателейОстатки
ГДЕ
ТИПЗНАЧЕНИЯ(РазмещениеЗаказовПокупателейОстатки.ЗаказПокупателя) = ТИП(Документ.ВнутреннийЗаказ)
На первый взгляд, оба варианта должны возвращать идентичный результат. Однако платформа выдает ошибку в первом случае еще до начала выполнения самого запроса. Выясним причину такого поведения.
Главный секрет кроется в том, на каком этапе и как именно платформа проверяет типы данных. Давайте разберем по шагам механизмы работы этих операторов:
ССЫЛКА проверяется платформой на этапе компиляции запроса. Платформа обращается к метаданным конфигурации и проверяет: может ли поле ЗаказПокупателя в принципе содержать тип Документ.ВнутреннийЗаказ. Если в настройках измерения в конфигураторе этот тип не выбран (не стоит галочка), платформа считает такой запрос заведомо ошибочным и прерывает выполнение с сообщением о несовместимости типов.ТИПЗНАЧЕНИЯ работает иначе. Она вычисляет тип значения непосредственно в момент выполнения запроса для каждой конкретной записи в базе данных. Для этой функции не важно, что прописано в метаданных поля — она просто сравнивает фактический идентификатор типа с указанным эталоном. Поэтому такой запрос "проходит" проверку и выполняется, даже если в метаданных связь не установлена.Таким образом, если вы получили ошибку «Несовместимые типы», это прямой сигнал: в составе типа реквизита (или измерения регистра) не указан тот тип объекта, который вы пытаетесь проверить.
Возникает логичный вопрос: если ТИПЗНАЧЕНИЯ работает всегда, зачем вообще использовать ССЫЛКА? Ответ кроется в оптимизации SQL-запросов. Проанализируем, во что превращаются эти команды на уровне СУБД:
Оператор ССЫЛКА транслируется в очень простое условие. В таблицах SQL для составных типов данных выделяется отдельное поле (обычно с суффиксом _TYPE), где хранится числовой идентификатор типа. Платформа просто подставляет нужное число в запрос. Это работает максимально быстро.
Конструкция ТИПЗНАЧЕНИЯ(...) = ТИП(...) может быть интерпретирована СУБД более сложным образом, особенно в старых версиях платформы или при использовании сложных соединений. Использование ССЫЛКА считается "лучшей практикой" (best practice) в 1С, так как она более жестко контролирует логическую целостность запроса. Для анализа итогового SQL-кода и логов технологического журнала можно применить консоль запросов со схемой и логом технологического журнала.
Рассмотрим ситуацию, когда в поле составного типа хранится Неопределено или NULL (например, при левом соединении). Многие разработчики опасаются, что оператор ССЫЛКА в таких случаях выдаст ошибку. Проанализируем ситуацию:
Неопределено, условие Поле ССЫЛКА Тип просто вернет Ложь. Ошибки не будет.ССЫЛКА к литералу Неопределено напрямую (например, ГДЕ Неопределено ССЫЛКА Справочник.Контрагенты), платформа выдаст ошибку, так как у литерала Неопределено вообще нет типа, совместимого со ссылочными типами.Посмотрим на пример правильной обработки:
ВЫБРАТЬ
Продажи.Номенклатура
ИЗ
РегистрНакопления.Продажи КАК Продажи
ГДЕ
Продажи.ДокументОснование ССЫЛКА Документ.РеализацияТоваровУслуг
ИЛИ Продажи.ДокументОснование ССЫЛКА Документ.ОтчетОРозничныхПродажах
В данном примере, если ДокументОснование будет пуст (Неопределено), запрос корректно вернет пустой результат без ошибок.
Если вы столкнулись с ошибкой «Несовместимые типы "ССЫЛКА"», выполните следующие действия:
ССЫЛКА попробуйте явно привести тип:
ВЫБРАТЬ
ВЫРАЗИТЬ(Т_Данные.Ссылка КАК Документ.ВнутреннийЗаказ) КАК Заказ
ПОМЕСТИТЬ ВТ_Уточненная
ИЗ
Т_Данные
ТИПЗНАЧЕНИЯ. Но помните, что это обходной путь, указывающий на несоответствие структуры данных вашим задачам.Мы выяснили, что ошибка «Несовместимые типы» — это не баг платформы, а строгий механизм контроля. Оператор ССЫЛКА защищает разработчика от запросов к данным, которых в этом поле быть не может согласно архитектуре базы. Используйте его всегда, когда это возможно, и внимательно следите за составом типов ваших реквизитов. Это обеспечит не только стабильную работу программы, но и высокую скорость выполнения запросов к базе данных.