При разработке и кастомизации конфигураций на платформе «1С:Предприятие 8» разработчики часто сталкиваются с ситуацией, когда стандартный или добавленный общий реквизит (например, омУИД) внезапно перестает считываться в запросах. Ошибка вида «Поле не найдено "ИмяСправочника.Владелец.ИмяРеквизита"» или «Поле не найдено "ИмяСправочника.Элемент.ИмяРеквизита"» прерывает выполнение программы в самый неподходящий момент. Рассмотрим детально, почему возникает эта проблема, как функционируют механизмы платформы в данный момент и какими способами мы можем гарантированно устранить эту ошибку.
Для того чтобы понять корень проблемы, проанализируем, как платформа 1С обрабатывает обращение к реквизитам связанных объектов через точку в теле запроса (разыменование ссылочных полей). Когда мы пишем в запросе конструкцию ВидыКИФ.Владелец.омУИД, СУБД выполняет неявное левое соединение (LEFT JOIN) таблицы справочника ВидыКИФ с таблицами всех объектов, которые могут выступать в роли его владельца.
Аналогично происходит и при обращении к реквизиту через составное поле, например, Бюджеты.Элемент.омУИД. Платформа пытается соединить таблицу справочника Бюджеты со всеми таблицами типов данных, входящих в составной тип поля Элемент.
Выделим ключевые технические причины, по которым это соединение завершается ошибкой СУБД:
Владелец или Элемент содержит несколько возможных типов данных (например, владельцами справочника могут быть как Организации, так и Контрагенты), платформа будет строить левое соединение со всеми этими таблицами. Если хотя бы у одного из этих справочников общий реквизит омУИД отключен в составе, вся конструкция запроса упадет с ошибкой «Поле не найдено».---
Это самый очевидный и фундаментальный способ решения проблемы. Нам необходимо убедиться, что общий реквизит физически назначен всем объектам, участвующим в цепочке запроса. Разберем этот процесс по шагам:
Общие, далее развернем подветку Общие реквизиты и найдем наш реквизит (в нашем примере это омУИД).ВидыКИФ) или все справочники, входящие в составной тип реквизита Элемент (для справочника Бюджеты).Использовать. Если там стоит значение Не использовать, то платформа не создает соответствующее поле в таблице СУБД, что и приводит к ошибке в запросе.Важное примечание: Если у общего реквизита свойство «Автоиспользование» установлено в значение Использовать, это означает, что реквизит автоматически добавляется ко всем вновь создаваемым объектам. Однако для старых объектов или объектов с индивидуальными настройками использование могло быть отключено вручную. Всегда проверяйте конкретные флаги в списке состава!
---
Что делать, если мы пишем универсальную обработку и не имеем возможности или права менять состав общего реквизита в основной конфигурации? Или если поле имеет составной тип, и у некоторых типов этого состава реквизита действительно быть не должно?
В таких случаях лучшей практикой разработки в среде «1С:Предприятие» является использование функции языка запросов ВЫРАЗИТЬ. Эта функция выполняет приведение типа на уровне СУБД и заставляет платформу делать левое соединение только с одной конкретной таблицей, отсекая все лишние типы данных.
Давайте посмотрим, как выглядел проблемный запрос из первого сообщения темы:
ВЫБРАТЬ
ВидыКИФ.Ссылка КАК Ссылка,
ЕСТЬNULL(ВидыКИФ.Владелец.омУИД, "") КАК OwnerID
ИЗ
Справочник.ВидыКИФ КАК ВидыКИФ
Если поле Владелец имеет составной тип, или если у какого-то из владельцев отключен реквизит омУИД, этот запрос вернет ошибку. Перепишем его правильно с использованием конструкции ВЫРАЗИТЬ:
ВЫБРАТЬ
ВидыКИФ.Ссылка КАК Ссылка,
ЕСТЬNULL(ВЫРАЗИТЬ(ВидыКИФ.Владелец КАК Справочник.Организации).омУИД, "") КАК OwnerID
ИЗ
Справочник.ВидыКИФ КАК ВидыКИФ
В данном примере мы явно указали системе, что нас интересует владелец только с типом Справочник.Организации. Платформа построит соединение только с таблицей справочника организаций, у которого общий реквизит гарантированно включен. Для всех остальных типов владельцев (если они будут в базе) функция вернет значение NULL, которое функция ЕСТЬNULL успешно заменит на пустую строку.
Теперь проанализируем вторую ошибку из темы, связанную со справочником Бюджеты и его реквизитом Элемент. Исходный нерабочий запрос выглядел так:
ВЫБРАТЬ
Бюджеты.Ссылка КАК Ссылка,
ЕСТЬNULL(Бюджеты.Элемент.омУИД, "") КАК ElementBID
ИЗ
Справочник.Бюджеты КАК Бюджеты
Применим аналогичный подход с явным приведением типов. Допустим, реквизит Элемент может содержать ссылки на справочники СтатьиОборотов и Проекты. Мы точно знаем, что общий реквизит используется только в статьях оборотов. Перепишем запрос следующим образом:
ВЫБРАТЬ
Бюджеты.Ссылка КАК Ссылка,
ЕСТЬNULL(ВЫРАЗИТЬ(Бюджеты.Элемент КАК Справочник.СтатьиОборотов).омУИД, "") КАК ElementBID
ИЗ
Справочник.Бюджеты КАК Бюджеты
Использование ВЫРАЗИТЬ не только решает проблему с ошибкой «Поле не найдено», но и существенно увеличивает скорость выполнения запроса СУБД, так как избавляет оптимизатор от необходимости строить множественные избыточные соединения (LEFT JOIN) со всеми таблицами составного типа.
---
Если вы ведете разработку внутри расширения конфигурации, поведение платформы может отличаться от работы с основной конфигурацией. Проанализируем возможные проблемы:
омУИД добавлен в ваше расширение. Если его там нет, конструктор запросов расширения не сможет его обработать.ВидыКИФ) внутри расширения. Проверьте, заимствовано ли свойство Владельцы. Если свойство не перенесено в расширение, платформа в контексте выполнения расширения может «не знать» о связи подчинения, что приведет к невозможности обратиться к полю через точку. Для решения добавьте свойство владельцев в расширение и установите флаг контроля.---
Мы подробно разобрали природу ошибки «Поле не найдено» при работе с общими реквизитами в запросах 1С. Для оперативного решения проблемы мы рекомендуем придерживаться следующего алгоритма действий:
ВЫРАЗИТЬ для принудительного ограничения типов составных полей. Это наиболее безопасный, надежный и производительный метод написания запросов.