Как исправить ошибку «в условиях соединения запроса не допускается обращение к табличным частям» в 1С?

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

При разработке сложных отчетов или обработок в платформе 1С разработчики часто сталкиваются с ситуацией, когда запрос прекрасно выполняется у пользователя с полными правами (администратора), но при запуске под ограниченными правами выбывает с ошибкой: «в условиях соединения запроса не допускается обращение к табличным частям».

Рассмотрим подробно причины возникновения этой проблемы и разберем по шагам правильные способы её устранения.

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

Ошибка возникает из-за использования неявного обращения к реквизитам табличной части через точку в секции ПО (условие соединения). Например, если написать следующее условие:


ЛЕВОЕ СОЕДИНЕНИЕ ЗначениеСвойств КАК ЗначениеСвойств
    ПО ВходящийДокумент.ДополнительныеРеквизиты.Значение = ЗначениеСвойств.Ссылка

Здесь ВходящийДокумент.ДополнительныеРеквизиты является табличной частью. В языке запросов 1С синтаксически запрещено разыменовывать поля табличных частей через точку в секции соединения ПО.

Почему же запрос работает под администратором? Ответ кроется в механизме RLS (Record-Level Security) — ограничении доступа на уровне записей:

  1. У администратора: Права доступа не ограничены, механизм RLS выключен. В некоторых случаях платформа оптимизирует или «прощает» синтаксические огрехи запроса, если они не вызывают конфликтов на уровне генерации SQL-кода.
  2. У обычных пользователей: Для пользователей с ограниченными правами платформа 1С автоматически модифицирует текст запроса, внедряя подзапросы RLS в секции отборов и соединений. При автоматической перестройке запроса неявное обращение к табличной части попадает в генерируемые условия, что вызывает жесткую синтаксическую проверку и блокируется платформой.

Способ 1. Явное соединение таблицы табличной части

Наиболее простое и быстрое решение — отказаться от обращения через точку и явно присоединить табличную часть как отдельную таблицу в запросе.

Разберем пример реализации этого подхода:


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

Важное замечание: При прямолинейном левом соединении с табличной частью нужно помнить, что результат запроса может размножиться (произойдет дублирование строк шапки документа), если в табличной части содержится несколько строк. Если требуется получать только уникальные значения или агрегированные данные, следует использовать группировку СГРУППИРОВАТЬ ПО или временные таблицы.

Способ 2. Предварительная выборка табличной части во временную таблицу

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

Проанализируем пример использования временных таблиц:


// ПАКЕТ 1: Выбираем данные из табличной части документа
ВЫБРАТЬ РАЗЛИЧНЫЕ
    ТЧДока.Ссылка КАК ДокументСсылка,
    ТЧДока.Значение КАК ЗначениеРеквизита
ПОМЕСТИТЬ ВТ_ДопРеквизиты
ИЗ
    Документ.ВходящийДокумент.ДополнительныеРеквизиты КАК ТЧДока
ИНДЕКСИРОВАТЬ ПО
    ДокументСсылка,
    ЗначениеРеквизита
;

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

Этот способ является наиболее безопасным и стандартным с точки зрения стандартов разработки 1С. Он корректно обрабатывается механизмами RLS и предотвращает снижение скорости работы отчета.

Способ 3. Использование привилегированного режима

Если запрос выполняется на стороне сервера (например, в модуле менеджера или в серверной функции обработки) и согласно бизнес-логике пользователю разрешено читать эти данные без применения ограничений прав RLS, можно отключить проверку прав на время выполнения кода.

Посмотрим, как обернуть вызов запроса в привилегированный режим:


УстановитьПривилегированныйРежим(Истина);

Запрос = Новый Запрос;
Запрос.Текст = "..."; // Ваш текст запроса
РезультатЗапроса = Запрос.Выполнить();

УстановитьПривилегированныйРежим(Ложь);

Использование метода УстановитьПривилегированныйРежим() отключает RLS для текущего фрагмента кода, благодаря чему платформа не модифицирует текст запроса для обычного пользователя, и ошибка не возникает.

Рекомендации

  1. Избегайте разыменования ссылочных полей через точку (например, Документ.ТабличнаяЧасть.Поле) в секциях ГДЕ, ПО и УПОРЯДОЧИТЬ ПО.
  2. Всегда проверяйте работу созданных отчетов и запросов под пользователем с ограниченными правами, чтобы своевременно выявить проблемы с RLS.
  3. Для работы с табличными частями отдавайте предпочтение выбору данных во временные таблицы с явной индексацией соединяемых полей.
← На главную