При обновлении платформы «1С:Предприятие» или повышении режима совместимости конфигурации до версий 8.3.21 и выше, разработчики часто сталкиваются с тем, что ранее стабильно работающие динамические списки начинают выдавать ошибки. Самые распространенные из них: невозможность сравнения полей неограниченной длины, «потеря» системных полей в виртуальных таблицах и сложности с использованием временных таблиц. В этой статье мы подробно разберем, как адаптировать ваши запросы к новым требованиям платформы.
Разберем ситуацию, когда нам необходимо использовать данные из временной таблицы (ВТ) в динамическом списке. Напрямую передать МенеджерВременныхТаблиц в динамический список невозможно, так как объект ДинамическийСписок самостоятельно управляет контекстом выполнения запроса. Однако, начиная с версии платформы 8.3.20, мы можем использовать пакетные запросы непосредственно в тексте запроса динамического списка. Для отладки таких сложных конструкций вам пригодится консоль запросов с полной поддержкой пакетных запросов и временных таблиц.
Рассмотрим, как это реализовать. Ранее программисты были вынуждены отказываться от ВТ в пользу сложных вложенных запросов, что негативно сказывалось на производительности. Теперь мы можем поместить данные во временную таблицу в первом запросе пакета (стоит также учитывать новые возможности, такие как добавление данных в существующую временную таблицу), а в последнем — выбрать их для отображения в списке. Проанализируем пример структуры такого запроса:
ВЫБРАТЬ
Номенклатура.Ссылка КАК Ссылка,
Номенклатура.ТорговоеНаименование КАК ТорговоеНаименование
ПОМЕСТИТЬ втТорговые
ИЗ
Справочник.Номенклатура КАК Номенклатура
ГДЕ
Номенклатура.ТорговоеНаименование <> ЗНАЧЕНИЕ(Справочник.ТорговыеНаименования.ПустаяСсылка)
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
СМНН.Ссылка КАК СМНН,
ТорговыеНаименования.ТорговоеНаименование КАК ТорговоеНаименование
ИЗ
Справочник.СМНН КАК СМНН
ЛЕВОЕ СОЕДИНЕНИЕ втТорговые КАК ТорговыеНаименования
ПО СМНН.ДействующиеВеществаМНН = ТорговыеНаименования.ДействующиеВеществаМНН
Важное ограничение: помните, что механизмы динамического списка (отборы, поиск, группировки) будут применяться платформой только к последнему запросу пакета. Если ваша временная таблица слишком велика, это может привести к деградации производительности, так как ВТ будет пересчитываться при каждом обновлении списка.
Одной из наиболее острых проблем при переходе на режим совместимости 8.3.21 является ошибка: «Нельзя сравнивать поля неограниченной длины». Это происходит из-за того, что оптимизатор запросов стал более строго следовать стандартам SQL. Поля типа «Строка» (без указания длины) или составные типы, включающие такие строки, больше не могут участвовать в операциях СОЕДИНЕНИЕ, ГДЕ или РАЗЛИЧНЫЕ.
Выясним причину: в СУБД (например, MS SQL Server) такие поля хранятся как типы NVARCHAR(MAX) или TEXT, для которых невозможна операция прямого сравнения или индексации. Чтобы решить эту проблему, мы должны явно ограничить длину поля с помощью оператора ВЫРАЗИТЬ. Проанализируем правильный подход к типизации:
ВЫБРАТЬ РАЗРЕШЕННЫЕ РАЗЛИЧНЫЕ
СМНН.Ссылка КАК СМНН,
ВЫРАЗИТЬ(СМНН.Наименование КАК СТРОКА(150)) КАК НаименованиеСокращенное
ИЗ
Справочник.СМНН КАК СМНН
ГДЕ
ВЫРАЗИТЬ(СМНН.ДополнительноеОписание КАК СТРОКА(200)) = &ПараметрОписание
Обязательно применяйте ВЫРАЗИТЬ во всех секциях запроса, где поле неограниченной длины участвует в логике сравнения или объединения. Если вы используете временные таблицы, типизацию лучше делать в момент помещения данных в ВТ, чтобы в последующих соединениях использовать уже типизированные колонки.
Рассмотрим еще одну странную особенность новых релизов: в расширениях конфигурации (особенно когда вы пытаетесь добавить дополнительную информацию в динамический список с помощью расширения) или при работе с виртуальными таблицами (например, СрезПоследних) платформа может «перестать видеть» системные поля, такие как Активность или НомерСтроки. Хотя конструктор запроса может отображать их как доступные, при выполнении кода возникает ошибка «Поле не найдено».
Это связано с тем, что виртуальные таблицы являются результатом агрегации данных физических таблиц. В новых режимах совместимости доступ к полям физической таблицы через виртуальную может быть ограничен. Разберем способ решения через явное соединение:
ВЫБРАТЬ
ЛистНазначений.Регистратор КАК Регистратор,
ФизическаяТаблица.НомерСтроки КАК НомерСтроки,
ФизическаяТаблица.Активность КАК Активность
ИЗ
РегистрСведений.ЛистВрачебныхНазначенийСтационар.СрезПоследних(&ДатаСреза, ) КАК ЛистНазначений
ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ЛистВрачебныхНазначенийСтационар КАК ФизическаяТаблица
ПО ЛистНазначений.Регистратор = ФизическаяТаблица.Регистратор
И ЛистНазначений.Период = ФизическаяТаблица.Период
Такой подход гарантирует получение системных данных напрямую из физической таблицы, исключая двусмысленность для оптимизатора запросов 1С.
Часто ошибки возникают в момент инициализации формы, когда параметры запроса динамического списка еще не установлены, а список уже пытается выполнить запрос. Посмотрим на ситуацию: если в тексте запроса используется условие ГДЕ Поле = &Параметр, и этот параметр не имеет значения по умолчанию, система может выдать ошибку типизации еще до срабатывания кода ПриСозданииНаСервере.
Рекомендуем использовать два подхода для повышения стабильности:
Отбор. Это позволяет платформе гибко строить запрос и избегать ошибок при пустых значениях. Более того, через расширения можно реализовать сложные условия, например, отборы на соответствие шаблону списком.ПриСозданииНаСервере, чтобы к моменту первой отрисовки списка все данные были инициализированы.Кстати, работая с настройками списка на сервере, можно реализовать не только отборы, но и интерактивные элементы, такие как флажок в динамическом списке. Рассмотрим пример перехода с параметров на отборы:
// Вместо изменения текста запроса используем объектную модель
ЭлементОтбора = Список.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("ИсточникФинансирования");
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлементОтбора.ПравоеЗначение = Объект.ИсточникФинансирования;
ЭлементОтбора.Использование = Истина;
Подведем итоги нашего анализа. Работа с динамическими списками в современных версиях 1С требует более аккуратного отношения к типам данных и структуре пакетов запросов. Помните основные правила:
ВЫРАЗИТЬ в соединениях.ГДЕ в программные настройки отбора компоновки данных.Следуя этим рекомендациям, вы сможете успешно перевести свои разработки на новые релизы платформы и обеспечить их высокую производительность и стабильность.