Передача таблицы значений в качестве параметра запроса является одним из самых мощных инструментов в арсенале разработчика платформы 1С:Предприятие. Этот механизм позволяет эффективно реализовать операции массового выборочного изменения данных, сложные фильтры по спискам и оптимизированные отчеты, избегая многократных обращений к базе данных. Понимание внутренней механики этого процесса критически важно для написания производительного кода.
Многие начинающие специалисты путают обычные массивы и таблицы значений, считая их взаимозаменяемыми при передаче в запрос. Однако сервер 1С обрабатывает эти структуры по-разному, и использование неверного типа данных может привести к падению запроса или существенному снижению скорости работы системы. В данной статье мы детально разберем синтаксис, особенности объявления временных таблиц и нюансы работы с типами данных.
Основная идея заключается в том, что таблица значений становится полноценной временной таблицей на стороне СУБД. Это открывает возможности для выполнения JOIN-операций, фильтрации через IN и создания сложных выборочных обновлений. Грамотное использование этого инструмента отличает код профессионала от любительских решений, особенно в высоконагруженных конфигурациях.
Основы объявления временной таблицы в запросе
Для того чтобы использовать таблицу значений в запросе, необходимо правильно объявить её в секции параметров метода Выполнить. Синтаксис требует указания имени параметра, типа данных и конкретного значения. Если тип данных указан неверно, платформа 1С выдаст ошибку компиляции или выполнения, прерывая работу алгоритма.
Ключевым моментом является использование конструкции ЗНАЧЕНИЕ при объявлении параметра. Без этого ключевого слова сервер попытается интерпретировать переданный объект как скалярное значение, что приведет к ошибке преобразования типов.
Рассмотрим базовый пример объявления. Мы создаем таблицу значений, заполняем её и передаем в запрос:
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Ссылка", ТипОписанияТипов(Новый ОписаниеТипов("СправочникСсылка.Номенклатура")));
ТЗ.Колонки.Добавить("Количество", ТипОписанияТипов(Новый ОписаниеТипов("Число")));
СтрокаТЗ = ТЗ.Добавить();
СтрокаТЗ.Ссылка = СсылкаНаОбъект;
СтрокаТЗ.Количество = 10;
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ * ИЗ &ПараметрТЗ КАК ПараметрТЗ";
Запрос.УстановитьПараметр("ПараметрТЗ", ЗНАЧЕНИЕ(ТЗ));
Результат = Запрос.Выполнить();
Обратите внимание на структуру описания типов колонок. Если вы не укажете тип явно или укажете его слишком широко (например, просто Строка без длины), СУБД может выбрать неоптимальный план выполнения. Жесткая типизация колонок таблицы значений помогает оптимизатору запросов 1С построить более эффективный план выборки данных.
⚠️ Внимание: При объявлении параметра в методе
УстановитьПараметробязательно используйте конструкциюЗНАЧЕНИЕ(..). Попытка передать переменную таблицы значений без этой обертки приведет к ошибке типа "Неверный тип значения параметра".
Всегда явно указывайте типы данных для колонок таблицы значений перед добавлением строк. Это предотвратит ошибки преобразования типов при передаче в SQL-сервер и ускорит выполнение запроса.
Синтаксис использования в теле запроса
После того как параметр объявлен, его можно использовать в тексте запроса как обычную таблицу. Для этого используется оператор ИЗ с указанием имени параметра. Важной особенностью является то, что к таблице значений можно применять псевдонимы, что делает код более читаемым и позволяет избежать конфликтов имен полей приJOIN-операциях.
Часто возникает необходимость отфильтровать данные основной таблицы по списку, переданному в таблице значений. В этом случае конструкция ВНУТРИ (IN) работает наиболее эффективно. Однако, если таблица значений содержит дополнительные атрибуты (например, коэффициенты или флаги), лучше использовать соединение ЛЕВОЕ СОЕДИНЕНИЕ или ВНУТРЕННЕЕ СОЕДИНЕНИЕ.
Пример использования таблицы значений для фильтрации списка документов:
Запрос.Текст =
"ВЫБРАТЬ
| ДокументыРеализация.Ссылка,
| ДокументыРеализация.Дата,
| ДокументыРеализация.Сумма
|ИЗ
| Документ.РеализацияТоваровУслуг КАК ДокументыРеализация
|ВНУТРЕННЕЕ СОЕДИНЕНИЕ &ТаблицаФильтр КАК ТаблицаФильтр
|ПО ДокументыРеализация.Ссылка = ТаблицаФильтр.Ссылка";
Использование внутреннего соединения гарантирует, что в выборку попадут только те записи, которые присутствуют в переданной таблице значений. Это особенно удобно при реализации отчетов "по выбранным позициям" или при проведении групповых операций обработки данных, где список объектов формируется динамически в коде.
Работа с типами данных и структурой колонок
Одной из самых частых проблем при работе с таблицами значений является несоответствие типов данных между колонками таблицы и полями основной таблицы в запросе. Платформа 1С пытается автоматически привести типы, но в сложных случаях это может привести к ошибкам или unexpected behavior. Особенно внимательно следует относиться к полям типа УникальныйИдентификатор и составным типам.
Если в таблице значений используется составной тип (например, СправочникСсылка.Номенклатура И СправочникСсылка.ХарактеристикиНоменклатуры), а в запросе происходит сравнение с полем, имеющим другой составной тип, может потребоваться явное приведение типов. В некоторых версиях платформы это решается автоматически, но полагаться на это не стоит.
Структура колонок должна быть определена до начала заполнения таблицы. Динамическое добавление колонок после заполнения строк невозможно. Это требует от разработчика заранее знать структуру данных, которые будут переданы в запрос. Если структура динамическая, рекомендуется использовать универсальные колонки типа Строка с достаточной длиной или ХранилищеЗначения, хотя последний вариант менее производителен.
| Тип колонки в ТЗ | Рекомендуемое использование | Особенности в запросе |
|---|---|---|
| Число | Количества, суммы, рейтинги | Автоматическое масштабирование |
| Строка (N) | Коды, артикулы, текстовые фильтры | Важно указать длину для оптимизации |
| Ссылка | Связи с документами и справочниками | Требует точного совпадения типа ссылки |
| Дата | Периоды, даты операций | Хранится с точностью до секунды |
| Булево | Флаги, признаки отбора | Эффективно для фильтрации JOIN |
При работе с большими объемами данных тип ХранилищеЗначения может стать узким местом, так как требует сериализации и десериализации данных. Используйте его только тогда, когда структура данных действительно сложная и не может быть представлена плоской таблицей. В 95% случаев плоская структура с типизированными колонками работает быстрее и надежнее.
⚠️ Внимание: Длина строковых полей в таблице значений влияет на размер временной таблицы в СУБД. Не задавайте длину
Строка(1000), если достаточноСтрока(50). Избыточная длина увеличивает объем передаваемых данных и потребление оперативной памяти сервера.
Оптимизация производительности при больших объемах
Когда таблица значений содержит десятки или сотни тысяч строк, подход к её использованию должен меняться. Передача огромной таблицы в параметр запроса создает нагрузку на канал связи между сервером приложений и СУБД. В таких случаях важно оценить целесообразность использования именно этого метода по сравнению с созданием временной таблицы на стороне базы данных через язык запросов.
Оптимизатор запросов 1С старается построить эффективный план, но при очень больших таблицах значений он может выбрать неоптимальный путь, например, полный перебор вместо использования индексов. Чтобы помочь оптимизатору, убедитесь, что поля, участвующие в соединениях (ПО), имеют индексы в основных таблицах базы данных.
Также следует учитывать ограничение на размер пакета данных. Если таблица значений слишком велика, она может быть разбита на несколько пакетов при передаче, что увеличит время выполнения. В критических случаях по производительности рассмотрите альтернативу: запись данных во временную таблицу на диске с помощью запроса ПОМЕСТИТЬ, если логика приложения это позволяет.
Секрет высокой производительности
Если вы передаете таблицу значений только для фильтрации по ссылкам, убедитесь, что в основной таблице есть индекс по полю ссылки. Без индекса соединение с большой таблицей значений вызовет Full Table Scan и "повесит" базу.
Мониторинг производительности с помощью технологического журнала (ТЖ) или консоли запросов поможет выявить проблемы. Обратите внимание на длительность этапа "Получение данных" и количество чтений. Если эти показатели высоки, возможно, стоит пересмотреть архитектуру взаимодействия с данными или разбить процесс на несколько этапов.
Частые ошибки и способы их устранения
Разработчики часто сталкиваются с рядом типовых ошибок при работе с таблицами значений. Самая распространенная — попытка обратиться к несуществующей колонке в тексте запроса. Поскольку таблица значений формируется динамически в коде, опечатка в имени колонки при добавлении или в тексте запроса приведет к ошибке выполнения, которую не всегда легко отловить на этапе компиляции.
Еще одна проблема — пустая таблица значений. Если в коде таблица осталась пустой, а в запросе используется ВНУТРЕННЕЕ СОЕДИНЕНИЕ, результат запроса также будет пустым. Это часто приводит к логическим ошибкам в программе, когда пользователь ожидает увидеть данные, а получает пустой отчет. Всегда проверяйте количество строк в таблице перед выполнением запроса.
Ошибки приведения типов возникают, когда в колонку таблицы значений пытаются записать значение несовместимого типа. Например, запись строки в колонку типа Число вызовет исключение. Строгая типизация на этапе создания колонок помогает избежать этой проблемы, заставляя разработчика явно контролировать данные.
☑️ Диагностика ошибок запроса
⚠️ Внимание: Интерфейс и возможности работы с запросами могут незначительно отличаться в зависимости от версии платформы 1С и используемой СУБД (MSSQL, PostgreSQL, Oracle). Детали реализации оптимизации могут меняться в новых релизах.
Продвинутые техники: Вложенные запросы и агрегация
Таблица значений как параметр открывает двери для сложных аналитических выборок. Вы можете использовать её не только для фильтрации, но и как источник данных для агрегации. Например, можно передать таблицу с плановыми показателями и сравнить их с фактическими данными из базы, выполнив группировку прямо в запросе.
Вложенные запросы с использованием таблицы значений позволяют создавать гибкие отчеты. Представьте ситуацию, когда пользователь выбирает несколько группировок для отчета. Вы можете сформировать таблицу значений с выбранными полями группировки и динамически построить запрос, который сгруппирует данные именно по этим измерениям. Это требует аккуратной работы с конструктором запросов или ручного формирования текста запроса.
Использование функции ЕСТЬNULL в сочетании с таблицей значений позволяет реализовать логику "заполнения пробелов". Если в таблице значений есть эталонный список периодов или номенклатуры, левое соединение позволит вывести все позиции из эталона, даже если по ним нет фактических данных в основной таблице, подставив нули или пустые значения.
Таблица значений в параметре запроса — это мост между логикой приложения на языке 1С и мощью реляционной СУБД. Правильное использование этого механизма позволяет перенести тяжелые вычисления на сторону базы данных, разгрузив сервер приложений.
Освоение этих техник переводит разработчика на новый уровень. Умение комбинировать табличные значения, временные таблицы и сложные условия соединения позволяет решать задачи, которые раньше требовали написания сложных циклов в коде, делая решения более декларативными и быстрыми.
Можно ли передавать таблицу значений в хранимую процедуру?
Напрямую передать таблицу значений 1С в нативную хранимую процедуру СУБД (например, на T-SQL или PL/SQL) стандартными средствами языка 1С невозможно. Таблица значений существует в контексте сервера 1С. Однако можно выгрузить данные во временную таблицу СУБД через запрос 1С, а затем вызвать хранимую процедуру, работающую с этой временной таблицей.
В чем разница между Таблицей Значений и Временной Таблицей в запросе?
Таблица значений — это объект языка 1С, существующий в памяти сервера приложений. Временная таблица в запросе (созданная через ПОМЕСТИТЬ) — это объект на стороне СУБД. Таблицу значений можно передать как параметр, а временную таблицу можно использовать только в пределах сессии соединения с базой данных после её создания запросом.
Как очистить таблицу значений перед использованием?
Для очистки таблицы значений используйте метод Очистить(). Это удалит все строки, но сохранит структуру колонок. Если нужно удалить и колонки тоже, создайте новый экземпляр объекта: ТЗ = Новый ТаблицаЗначений. Очистка предпочтительнее пересоздания, если структура колонок сложная и формируется динамически.
Есть ли ограничение на количество строк в таблице значений?
Жесткого программного ограничения на количество строк в объекте ТаблицаЗначений в 1С нет, оно ограничено только доступной оперативной памятью сервера. Однако при передаче в запрос рекомендуется не превышать разумные пределы (сотни тысяч строк), чтобы не перегружать канал связи и оптимизатор СУБД.
Можно ли сортировать таблицу значений перед передачей в запрос?
Да, таблицу значений можно отсортировать методом Сортировать() перед передачей в запрос. Однако порядок строк в таблице значений не гарантирует порядок выдачи результатов в запросе, если в тексте запроса явно не указано УПОРЯДОЧИТЬ ПО. Сортировка внутри ТЗ может быть полезна для логики алгоритма до запроса.