Будет ли ошибка при соединении таблиц в запросе по полям с определяемыми типами?

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

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

Механика работы определяемого типа в запросах

Для начала разберем природу этого объекта. Определяемый тип — это объект метаданных, который позволяет централизованно описывать составной тип данных и использовать его в различных частях конфигурации. С точки зрения платформы и механизма выполнения запросов, работа с полем, имеющим ОпределяемыйТип, практически идентична работе с обычным составным типом (несколькими типами, выбранными непосредственно в свойствах реквизита).

Рассмотрим ситуацию, описанную в вопросе: мы выполняем левое соединение двух регистров по полям с разными (или частично пересекающимися) определяемыми типами. Проанализируем пример запроса:


ВЫБРАТЬ
    Регистр1.Номенклатура,
    Регистр2.Количество
ИЗ
    РегистрНакопления.Регистр1 КАК Регистр1
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.Регистр2 КАК Регистр2
    ПО Регистр1.ОбъектСвязи = Регистр2.Владелец

Если в Регистр1.ОбъектСвязи хранится ссылка на Справочник.Договоры, а в описании Регистр2.Владелец этот справочник отсутствует, система не выдаст исключение. В этом случае условие соединения просто вернет значение Ложь, и для данной записи левой таблицы поля правой таблицы будут заполнены значениями NULL. Это происходит потому, что на уровне СУБД сравнение идет не только по идентификатору ссылки, но и по идентификатору типа.

Структура хранения в SQL и влияние на результат

Чтобы понять, почему не возникает ошибки, нам нужно заглянуть "под капот" системы. При использовании составных или определяемых типов в SQL-базе поле превращается в несколько физических колонок. Обычно это:

  1. Колонка для хранения уникального идентификатора ссылки (GUID).
  2. Колонка для хранения кода типа (идентификатор метаданных).
  3. (В некоторых случаях) Колонки для хранения простых типов (число, строка, дата), если они включены в состав.

Когда мы пишем условие соединения ПО Регистр1.ОпределяемыйТип1 = Регистр2.ОпределяемыйТип2, платформа 1С автоматически транслирует это в SQL-запрос, который сравнивает пары колонок (тип и значение). Если в левой таблице тип "Справочник.Контрагенты", а в правой таблице в списке допустимых типов такого справочника вообще нет, SQL-сервер сравнит идентификаторы типов, увидит несовпадение и корректно вернет пустой результат для этой пары строк.

Оптимизация производительности: использование оператора ВЫРАЗИТЬ

Несмотря на то, что ошибка не возникает, использование "чистого" соединения по определяемому типу может быть крайне медленным на больших объемах данных. Разберем ситуацию: если в определяемый тип входит 20 различных справочников и документов, СУБД приходится выполнять сложную проверку при соединении, что часто приводит к неоптимальному плану запроса и игнорированию индексов.

Для ускорения работы рекомендуется использовать оператор ВЫРАЗИТЬ (или EXPRESS в англоязычном варианте), если нам заранее известно, какой конкретно тип данных мы ожидаем в соединении. Проанализируем правильный подход:


ВЫБРАТЬ
    Регистр1.Номенклатура,
    Регистр2.Количество
ИЗ
    РегистрНакопления.Регистр1 КАК Регистр1
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.Регистр2 КАК Регистр2
    ПО ВЫРАЗИТЬ(Регистр1.ОбъектСвязи КАК Справочник.Контрагенты) = ВЫРАЗИТЬ(Регистр2.Владелец КАК Справочник.Контрагенты)
ГДЕ
    Регистр1.ОбъектСвязи ССЫЛКА Справочник.Контрагенты

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

Нюансы с "Пустой ссылкой" и "Неопределено"

Частой причиной "пропажи" данных при соединении по определяемым типам является различие между значениями Неопределено и ПустаяСсылка. Выясним причину этого поведения:

Если в одном регистре поле содержит Неопределено, а в другом — пустую ссылку справочника, соединение не сработает. Визуально в отчетах оба поля могут выглядеть пустыми, что вводит разработчика в заблуждение. Проанализируем это при отладке, проверяя именно тип значения в полях.

Влияние на RLS (Ограничение доступа)

Рассмотрим еще один важный аспект. Если вы используете определяемые типы в запросах, которые выполняются под пользователем с ограниченными правами (RLS), это может существенно замедлить систему. Платформа 1С для каждой таблицы, входящей в определяемый тип, добавляет подзапросы для проверки прав доступа. Если в типе 15 объектов, SQL-запрос может разрастись до гигантских размеров с множеством JOIN и UNION.

В таких случаях рекомендуется:

  1. Минимизировать количество типов в одном ОпределяемомТипе.
  2. По возможности выгружать промежуточные данные во временные таблицы, где типы уже будут ограничены с помощью ВЫРАЗИТЬ.

Подводя итог, можно сказать, что соединение по определяемым типам — это безопасная операция с точки зрения стабильности системы (ошибок "Exception" не будет), но она требует внимательности при работе с производительностью и понимания того, как данные представлены на физическом уровне базы данных.

← На главную