В современной разработке на платформе 1С:Предприятие 8 работа с наборами данных в памяти стала стандартом де-факто для построения сложной бизнес-логики. Разработчики часто сталкиваются с задачей, когда необходимо отфильтровать данные из базы, используя список значений, полученный из формы или другого источника. Именно здесь на сцену выходит ТаблицаЗначений, которая служит универсальным контейнером для временного хранения данных.

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

В этой статье мы подробно разберем механизм создания Таблицы значений, особенности добавления строк и, самое главное, синтаксис обращения к ней внутри языка запросов. Вы узнаете, как правильно объявлять поля, использовать временные таблицы и применять сложные условия фильтрации, опираясь на переданные из кода данные.

Создание и наполнение таблицы значений

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

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

⚠️ Внимание: Если вы планируете использовать строковые поля для соединения с таблицами базы данных, убедитесь, что длина строки в параметре достаточна. Усечение длинных строк при вставке в таблицу значений может привести к тому, что соединение в запросе не сработает корректно.

Рассмотрим пример создания таблицы для хранения списка номенклатуры, который мы будем использовать для отбора:

ТЗНоменклатура = Новый ТаблицаЗначений;

ТЗНоменклатура.Колонки.Добавить("Ссылка", ТипОписанияТипов("СправочникСсылка.Номенклатура"));

ТЗНоменклатура.Колонки.Добавить("Количество", ТипОписанияТипов("Число(15,2)"));

// Добавление строк

Строка = ТЗНоменклатура.Добавить;

Строка.Ссылка = Справочники.Номенклатура.НайтиПоНаименованию("Товар А");

Строка.Количество = 10;

  • 📌 Используйте метод Колонки.Добавить для явного объявления структуры перед заполнением.
  • 📌 Проверяйте соответствие типов данных при присваивании значений в ячейки.
  • 📌 Для булевых значений и дат используйте строгие типы описания, чтобы избежать ошибок сравнения.
💡

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

Синтаксис использования в языке запросов

Чтобы использовать созданную таблицу в запросе, её необходимо передать как параметр объекта Запрос. В тексте запроса такая таблица обращается по имени параметра, предваренному символом &. Платформа автоматически понимает, что передан объект ТаблицаЗначений, и позволяет обращаться к нему как к обычной таблице в предложении ИЗ.

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

Обращение к полям таблицы значений происходит стандартным образом через точку. Например, если параметр называется &ПараметрСписка, а поле в нем Код, то в условии выборки вы напишете &ПараметрСписка.Код. Компилятор запросов 1С корректно обрабатывает такие конструкции, генерируя необходимый SQL-код для конкретной СУБД.

Особенности работы с NULL в таблице значений

Если в таблице значений поле не заполнено, оно считается равным NULL. При сравнении в запросе помните, что NULL не равен NULL. Используйте оператор ЕСТЬ NULL или ЕСТЬ НЕ NULL для корректной обработки пустых значений.

Пример простого запроса с использованием параметра-таблицы:

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Реестр.Период,

| Реестр.Сумма

|ИЗ

| РегистрНакопления.Продажи КАК Реестр

|ГДЕ

| Реестр.Номенклатура В (&СписокНоменклатуры)";

Запрос.УстановитьПараметр("СписокНоменклатуры", ТЗНоменклатура);

Результат = Запрос.Выполнить;

  • 🚀 Оператор В является наиболее эффективным способом фильтрации по списку значений из таблицы.
  • 🚀 Имя параметра в методе УстановитьПараметр должно точно совпадать с именем в тексте запроса.
  • 🚀 Регистр букв в именах полей таблицы значений не имеет значения для платформы, но лучше соблюдать единый стиль.
📊 Какой способ передачи списка в запрос вы используете чаще?
Через параметр ТаблицаЗначений
Через временную таблицу на сервере
Через конкатенацию строк (НЕ рекомендуется)
Через цикл с параметрами

Соединение таблиц значений с данными базы

Одним из самых мощных инструментов разработчика является возможность выполнять JOIN (соединение) между таблицей значений и реальными таблицами базы данных. Это позволяет не просто фильтровать данные, но и дополнять их информацией, которая хранится только в памяти, или наоборот — обогащать данные из базы атрибутами из временного списка.

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

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

⚠️ Внимание: При соединении таблицы значений с регистром сведений или документом убедитесь, что типы ключевых полей совместимы. Например, соединение ссылки на элемент справочника с строковым представлением этой ссылки не сработает без явного приведения типов.

Рассмотрим пример левого соединения для получения актуальных остатков по списку товаров:

ТекстЗапроса = 

"ВЫБРАТЬ

| Список.Ссылка КАК Товар,

| Список.Количество КАК ПлановоеКоличество,

| Остатки.КоличествоОстаток КАК ФактическийОстаток

|ИЗ

| &ТЗСписок КАК Список

| ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК Остатки

| ПО Список.Ссылка = Остатки.Номенклатура";

💡

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

Фильтрация и сложные условия отбора

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

При фильтрации можно использовать стандартные операторы сравнения: =, <>, >, <. Особую роль играет оператор В, который проверяет вхождение значения основного запроса в список значений параметра. Это наиболее быстрый способ отбора по множеству значений, так как он оптимизирован на уровне движка запросов 1С.

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

  • 🔍 Оператор В работает быстрее, чем цепочка условий ИЛИ для большого списка значений.
  • 🔍 Можно фильтровать саму таблицу значений внутри запроса перед соединением с основными данными.
  • 🔍 Используйте псевдонимы для таблиц значений, чтобы сделать текст запроса короче и понятнее.

Пример фильтрации по нескольким колонкам таблицы значений:

"ВЫБРАТЬ

| Документы.Ссылка

|ИЗ

| Документ.РеализацияТоваровУслуг КАК Документы

|ГДЕ

| Документы.Контрагент В (&СписокКонтрагентов)

| И Документы.Дата >= &НачалоПериода"

Оптимизация больших списков

Если таблица значений содержит более 10 000 строк, рассмотрите возможность явного создания временной таблицы на сервере 1С перед основным запросом. Это может помочь оптимизатору СУБД лучше распределить ресурсы.

Работа с временными таблицами и параметрами

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

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

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

⚠️ Внимание: Не создавайте временные таблицы без необходимости. Для простых выборок прямая передача параметра-таблицы значений работает быстрее и потребляет меньше памяти сервера 1С.

Пример создания временной таблицы из параметра:

ТекстЗапроса = 

"ВЫБРАТЬ

| Параметр.Код,

| Параметр.Наименование

|ПОМЕСТИТЬ ВТ_Список

|ИЗ

| &ПараметрТЗ КАК Параметр;

|ВЫБРАТЬ

| Товары.Ссылка

|ИЗ

| Справочник.Номенклатура КАК Товары

| ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_Список КАК Список

| ПО Товары.Код = Список.Код";

☑️ Алгоритм работы со сложными параметрами

Выполнено: 0 / 5

Типичные ошибки и способы их решения

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

Еще одна частая ошибка — несовпадение имен полей. Если в таблице значений колонка называется КодЭлемента, а в запросе вы обращаетесь к Код, система выдаст ошибку выполнения. Всегда проверяйте имена колонок в отладчике или через метод Колонки перед установкой параметра.

Также стоит упомянуть проблему с пустой таблицей значений. Если вы передали в запрос параметр, который является пустой таблицей (нет ни одной строки), поведение запроса может отличаться в зависимости от используемого оператора. Например, соединение с пустой таблицей вернет пустой результат, что иногда ломает логику отчета, ожидающего хотя бы заголовки.

Тип ошибки Симптом Решение
Несовместимость типов Запрос выполняется, но результат пуст Привести типы в коде перед записью в ТЗ
Отсутствие индекса Медленное выполнение на больших данных Создать индекс по полю соединения в ТЗ
Ошибка синтаксиса Сообщение"Неизвестное поле" Проверить имена колонок и регистр букв
💡

Для отладки запросов с таблицами значений используйте Консоль Запросов. Вы можете скопировать код заполнения ТЗ и выполнить запрос в консоли, чтобы увидеть результат и план выполнения без запуска всей конфигурации.

Часто задаваемые вопросы (FAQ)

Можно ли передать таблицу значений из формы на сервер без создания объекта на сервере?

Да, это стандартная практика. Вы создаете таблицу значений на клиенте, заполняете её и передаете в серверный метод как аргумент. Платформа автоматически сериализует данные. Однако для больших объемов данных (сотни тысяч строк) это может увеличить время передачи по сети.

Как добавить индекс в таблицу значений для ускорения поиска?

Используйте метод Индексы.Добавить("ИмяПоля") у объекта ТаблицаЗначений сразу после создания колонок и перед заполнением данными. Это существенно ускорит операции соединения и сортировки внутри запроса.

Что делать, если количество строк в таблице значений превышает лимит параметров?

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

Можно ли использовать таблицу значений для обновления данных?

Напрямую оператором ОБНОВИТЬ таблицу значений в запросе нельзя, так как это временный набор данных. Но вы можете выбрать данные из таблицы значений и базы, а затем в цикле обновить регистры или документы, используя полученные ключи.

Как очистить таблицу значений перед повторным использованием?

Для очистки используйте метод Очистить. Он удаляет все строки, но сохраняет структуру колонок. Если нужно изменить и структуру, проще создать новый объект Новый ТаблицаЗначений.