Как исправить ошибку "Основная таблица динамического списка задана неверно" при использовании произвольного запроса в 1С?

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

При разработке форм списков документов в 1С:Предприятии 8.3 на управляемых формах, мы часто сталкиваемся с необходимостью отображения данных не только из основного объекта, но и из связанных таблиц, например, из табличных частей. Для этого в свойствах динамического списка устанавливается флаг "ПроизвольныйЗапрос", и мы пишем свой собственный запрос. Однако, в процессе работы, может возникнуть ошибка "Основная таблица динамического списка задана неверно". Давайте разберем, почему возникает эта ошибка и как ее эффективно исправить.

Анализ исходной проблемы и причины ошибки

Для предотвращения подобных ситуаций полезно проводить анализ конфигурации на наличие ошибок.

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

  1. Мы не указали основную таблицу в свойствах динамического списка, и при этом запрос, который мы написали, является некорректным или слишком сложным для автоматического определения ключевых полей.
  2. Наш произвольный запрос содержит логические ошибки, приводит к неполным данным или использует функционал, не поддерживаемый текущей версией платформы или режимом совместимости.
  3. Неправильно выбраны типы соединений таблиц, что приводит к отсечению части данных, которые должны быть в списке.
  4. Попытка включить целые табличные части документа в выборку основного запроса.

В нашем случае, пользователь столкнулся с этой проблемой при попытке добавить поле "Производитель" из табличной части документа "УпаковочныйЛист.Товары" в список документов.

Шаг 1: Проверка и настройка свойства "Основная таблица"

Прежде чем углубляться в запрос, нам следует убедиться, что свойство "Основная таблица" в настройках динамического списка указано правильно. Даже при использовании произвольного запроса, платформа может использовать это свойство для определения ключа списка и корректной работы с курсором данных. В данной ситуации, автор темы указал Документ.УпаковочныйЛист, что является верным для списка документов.

Шаг 2: Создание и отладка произвольного запроса

Самым важным этапом является написание корректного и эффективного запроса. Мы всегда рекомендуем проверять текст запроса в Консоли запросов 1С — для этого подойдёт консоль запросов и инструменты отладки 1С. Это позволяет быстро выявлять синтаксические ошибки, анализировать структуру выборки и проверять логику работы запроса до того, как мы вставим его в динамический список. В нашем случае, без проверки в консоли, автор столкнулся с рядом проблем, которые были выявлены уже при открытии формы.

Избегаем распространенных ошибок в запросе

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

  1. Не используйте ВЫБРАТЬ ПЕРВЫЕ N без необходимости.

    Наш первый запрос содержит конструкцию ВЫБРАТЬ ПЕРВЫЕ 1. Эта конструкция означает, что запрос вернет только одну первую строку из всей выборки. Для динамического списка, который должен отображать множество документов, такая конструкция абсолютно неприемлема, так как она не позволяет получить полный набор данных. Динамический список не сможет корректно отобразить все документы.

  2. Избегайте прямого включения табличных частей.

    Одной из критических ошибок, которая может приводить к проблемам, является попытка выбрать всю табличную часть документа как одно поле в основном запросе, например, ДокументУпаковочныйЛист.Товары. Табличная часть — это сложный объект, который не может быть просто так включен в список. Мы должны выбирать только конкретные поля из табличной части, которые нам необходимы, например, УпаковочныйЛистТовары.Номенклатура.Производитель. После удаления ДокументУпаковочныйЛист.Товары из запроса, ошибка в консоли исчезла, что подтверждает некорректность такого выбора.

  3. Правильное использование соединений: ЛЕВОЕ СОЕДИНЕНИЕ вместо ВНУТРЕННЕГО.

    Когда мы присоединяем данные из табличных частей документа, которые могут быть пустыми для некоторых документов, очень важно использовать ЛЕВОЕ СОЕДИНЕНИЕ (LEFT JOIN). Рассмотрим ситуацию:

    • ВНУТРЕННЕЕ СОЕДИНЕНИЕ (INNER JOIN): Если мы используем ВНУТРЕННЕЕ СОЕДИНЕНИЕ, то в выборку попадут только те документы, для которых есть соответствующие записи в присоединяемой таблице. Если у документа нет ни одной строки в табличной части (например, "Товары"), то этот документ не попадет в список. В нашем случае, 20 из 750 документов имели пустые табличные части, и ВНУТРЕННЕЕ СОЕДИНЕНИЕ не позволило бы им отобразиться, что приводило к ошибке или неполному списку.

    • ЛЕВОЕ СОЕДИНЕНИЕ (LEFT JOIN): Эта конструкция позволяет вывести все записи из левой таблицы (в нашем случае, из таблицы документов Документ.УпаковочныйЛист) независимо от того, есть ли соответствующие записи в правой таблице (табличной части Документ.УпаковочныйЛист.Товары). Если соответствующих записей нет, поля из правой таблицы будут иметь значение NULL. Это именно то, что нам нужно, чтобы отобразить все документы, даже те, у которых табличные части пусты, и при этом получить данные из табличной части, если они есть. В случае с полем "Поклажедатель", которое извлекается из табличной части, мы можем использовать функцию ЕстьNull(), чтобы обработать случаи, когда данные отсутствуют.

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

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

  4. Ограничения на использование временных таблиц.

    Наш первоначальный запрос включал использование временных таблиц (ПОМЕСТИТЬ ВТТовары). Важно знать, что использование временных таблиц в динамических списках поддерживается не во всех версиях платформы. В частности, в режиме совместимости 8.3.7 и ниже (как в нашем случае) временные таблицы в динамических списках не поддерживаются. Применение их в таком режиме приведет к ошибкам. Если вы столкнулись с подобной ситуацией, мы рекомендуем либо перепроектировать запрос, избегая временных таблиц (что было сделано в итоге), либо обновить платформу и/или режим совместимости до версии 8.3.8 или выше. При этом, даже в поддерживаемых версиях, временные таблицы не рекомендуется использовать для большого объема данных, так как они не кэшируются и могут снижать производительность.

Итоговый рекомендуемый подход к запросу

Основываясь на проделанном анализе и успешном решении проблемы, мы рекомендуем следующий запрос для динамического списка документа "УпаковочныйЛист", который будет корректно отображать все документы и при этом выводить "Поклажедателя" из первой строки табличной части (или NULL, если табличная часть пуста):


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

Этот запрос:

Дополнительные рекомендации для оптимизации динамических списков

Для того чтобы динамические списки работали быстро и без ошибок, мы рекомендуем придерживаться следующих практик:

  1. Динамическое считывание данных: Убедитесь, что это свойство включено. В этом режиме запросы выбирают небольшое количество записей, близкое к числу видимых строк таблицы, что значительно повышает производительность при работе с большими списками. Если динамическое считывание выключено и основная таблица не задана, запрос выполняется "как есть", что может привести к медленной работе при большом объеме данных.

  2. Индексирование полей: Для повышения скорости работы запросов мы рекомендуем индексировать поля, по которым выполняются соединения, наложены условия фильтрации, выведены как быстрые отборы, а также по которым выполняются сортировки или группировки.

  3. Избегание сложных конструкций: Старайтесь делать запросы максимально простыми, избегайте вложенных запросов и виртуальных таблиц, если их можно переделать (например, используя СКДБилдер для программной генерации). Динамические списки предъявляют высокие требования к скорости выполнения запросов.

  4. Проверка запросов: Всегда проверяйте запросы в Консоли запросов 1С перед их внедрением в динамический список. Это поможет на ранних этапах выявить синтаксические и логические ошибки и провести быстрый анализ данных.

  5. Иерархические списки: Для иерархических списков не рекомендуется устанавливать свойство НачальноеОтображениеДерева в "РаскрыватьВсеУровни" для избежания снижения скорости открытия, особенно при большом количестве элементов.

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

← На главную