При доработке форм списков документов или журналов в 1С:Предприятии 8.3 разработчики часто сталкиваются с необходимостью выводить дополнительные данные: сведения о распоряжениях, реквизиты связанных документов, перевозчиков или статусы маркировки. В попытке оптимизировать сложные выборки разработчики нередко переписывают текст запроса динамического списка на пакетный запрос с формированием временных таблиц. Однако при открытии формы возникает системная ошибка: «Основная таблица динамического списка задана неверно».
Разберем детально, почему платформа 1С выдает данное сообщение, как устроена работа динамического списка и какими способами можно правильно решить эту задачу.
Для понимания корня проблемы проанализируем, за что отвечает свойство ОсновнаяТаблица у динамического списка на управляемой форме. Когда в свойствах реквизита списка указана основная таблица (например, ЖурналДокументов.СкладскиеОрдера), платформа берет на себя управление следующими механизмами:
Механизм платформы жестко требует: если в свойствах динамического списка заполнено поле ОсновнаяТаблица, то таблица именно этого объекта метаданных должна присутствовать в явном виде в секции ИЗ или ЛЕВОЕ СОЕДИНЕНИЕ самого последнего (результирующего) запроса пакета.
Посмотрим на фрагмент завершающего запроса, который привел к ошибке:
ВЫБРАТЬ РАЗРЕШЕННЫЕ
СкладскиеОрдера.Ссылка КАК Ссылка,
СкладскиеОрдера.Дата КАК Дата,
...
ИЗ
ВТ_Ордера КАК СкладскиеОрдера
ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Итговая КАК ВТ_Итговая
ПО СкладскиеОрдера.Ссылка = ВТ_Итговая.Ссылка
В приведенном коде последняя выборка выполняется из временной таблицы ВТ_Ордера. Несмотря на то что во временную таблицу изначально помещались данные из ЖурналДокументов.СкладскиеОрдера, для платформы временная таблица — это абстрактный набор полей. Платформа не может связать строки результирующей выборки с физической таблицей базы данных, что и вызывает исключение.
Самое быстрое исправление в рамках существующего пакетного запроса — обеспечить явное присутствие основной таблицы в финальном запросе пакета. Перепишем финальную часть запроса так, чтобы выборка шла непосредственно из объекта метаданных, а вычисленные данные подтягивались из сформированной временной таблицы:
ВЫБРАТЬ РАЗРЕШЕННЫЕ
ЖурналДокументовСкладскиеОрдера.Ссылка КАК Ссылка,
ЖурналДокументовСкладскиеОрдера.Дата КАК Дата,
ЖурналДокументовСкладскиеОрдера.ПометкаУдаления КАК ПометкаУдаления,
ЖурналДокументовСкладскиеОрдера.Номер КАК Номер,
ЖурналДокументовСкладскиеОрдера.Проведен КАК Проведен,
ЖурналДокументовСкладскиеОрдера.Статус КАК Статус,
ЖурналДокументовСкладскиеОрдера.Комментарий КАК Комментарий,
ЖурналДокументовСкладскиеОрдера.ПомещениеОтправитель КАК ПомещениеОтправитель,
ЖурналДокументовСкладскиеОрдера.Приоритет КАК Приоритет,
ЖурналДокументовСкладскиеОрдера.ДатаОтгрузки КАК ДатаОтгрузки,
ЖурналДокументовСкладскиеОрдера.ЗаданиеНаПеревозку КАК ЗаданиеНаПеревозку,
ЖурналДокументовСкладскиеОрдера.ОтгрузкаПоЗаданиюНаПеревозку КАК ОтгрузкаПоЗаданиюНаПеревозку,
ЖурналДокументовСкладскиеОрдера.ПорядокДоставки КАК ПорядокДоставки,
ЖурналДокументовСкладскиеОрдера.ПолучательОтправитель КАК ПолучательОтправитель,
ЖурналДокументовСкладскиеОрдера.Тип КАК Тип,
ВТ_Итговая.Перевозчик КАК Перевозчик,
ВТ_Итговая.Распоряжение КАК ЗаказКлиента,
ВТ_Итговая.ЕстьСсылкаНаДокумент КАК ЕстьСсылкаНаДокумент,
ВТ_Итговая.СсылкаНаДокумент КАК СсылкаНаДокумент
ИЗ
ЖурналДокументов.СкладскиеОрдера КАК ЖурналДокументовСкладскиеОрдера
ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Итговая КАК ВТ_Итговая
ПО ЖурналДокументовСкладскиеОрдера.Ссылка = ВТ_Итговая.Ссылка
Теперь платформа четко видит таблицу ЖурналДокументов.СкладскиеОрдера в секции ИЗ и безошибочно сопоставляет строки списка.
Рассмотрим альтернативный вариант: если форма списка используется исключительно в режиме просмотра или выбора данных, и вам не требуются стандартные команды платформы (проведение документов, контекстное меню смены статусов и т. д.), можно снять требование платформы.
Для этого в палитре свойств реквизита динамического списка просто очистим свойство ОсновнаяТаблица (оставим его пустым). Ошибка исчезнет, однако необходимо учитывать ограничение: динамический список перестанет считывать данные «на лету» небольшими порциями при прокрутке.
Обратим внимание на критически важный аспект разработки: динамический список выполняет свой запрос многократно — при скроллинге, наложении отборов, сортировке, поиске и обновлении формы. Когда в запросе динамического списка создается цепочка временных таблиц без жестких отборов по периоду, СУБД вынуждена при каждом действии пользователя пересчитывать все промежуточные таблицы (ВТ_Распоряжения, ВТ_Реализации и т. д.) по всей базе данных целиком. Это быстро приводит к зависаниям интерфейса.
Кроме того, конструкция вида СкладскиеОрдера.Ссылка.Реквизит применительно к журналу документов заставляет платформу строить неявные левые соединения со всеми типами документов, входящими в журнал, что создает тяжелую нагрузку на СУБД.
Чтобы избежать падения производительности в высоконагруженных базах, разберем более эффективные подходы к решению подобной задачи:
ПриПолученииДанныхНаСервере: оставляем запрос динамического списка максимально простым (только выборка из журнала). В событии таблицы формы ПриПолученииДанныхНаСервере получаем массив ссылок только тех документов, которые отображаются на экране прямо сейчас (обычно 20–40 строк), и одним точечным запросом получаем связанные реализации, перемещения и перевозчиков, заполняя оформление строк. Нагрузка на сервер снижается в десятки раз.