Работа с табличными данными в 1С:Предприятие часто требует передачи целых таблиц в SQL-запросы как параметров. Это типичная задача при формировании сложных отчетов, аналитических выборок или интеграции с внешними системами. Однако стандартный механизм параметров запроса УстановитьПараметр не поддерживает прямую передачу объектов типа ТаблицаЗначений или ТабличнаяЧасть — только скалярные значения (числа, строки, даты) и массивы.

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

Особое внимание уделим недокументированным нюансам взаимодействия 1С и СУБД, которые влияют на скорость выполнения запросов с табличными параметрами. Например, почему передача массива из 10 000 строк может замедлить запрос в 50 раз по сравнению с временной таблицей, и как это обойти.

1. Метод временных таблиц: классический подход с максимальной производительностью

Самый универсальный и эффективный способ — создание временной таблицы в базе данных, заполнение её данными из 1С, а затем использование в запросе. Этот метод работает во всех версиях платформы (включая 8.2 и 8.3) и поддерживается всеми СУБД (Microsoft SQL Server, PostgreSQL, IBM DB2, Oracle).

Основное преимущество: данные передаются на сервер СУБД одним пакетом, что минимизирует сетевой трафик и ускоряет выполнение сложных запросов. Например, при фильтрации по 50 000 строк временная таблица будет работать в 10–100 раз быстрее, чем передача этих данных через параметры.

  • Плюсы: максимальная скорость, поддержка больших объемов данных (миллионы строк), совместимость со всеми СУБД.
  • ⚠️ Минусы: требует прав на создание временных таблиц, сложнее в реализации для новичков.
  • 🔧 Когда использовать: для отчетов с большими выборками, интеграции с внешними системами, сложных аналитических запросов.

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

// 1. Создаем временную таблицу

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

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

"ВЫБРАТЬ

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

| Товары.Артикул КАК Артикул

|ПОМЕСТИТЬ ВТ_Товары

|ИЗ

| Справочник.Товары КАК Товары

|ГДЕ

| Товары.ПометкаУдаления = ЛОЖЬ";

Запрос.Выполнить;

// 2. Заполняем её данными из таблицы значений

ТаблицаТоваров = ПолучитьТаблицуТоваров; // Ваша таблица значений

Для Каждого Строка Из ТаблицаТоваров Цикл

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

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

"ВСТАВИТЬ В ВТ_Товары (Ссылка, Артикул)

|ЗНАЧЕНИЯ (&Ссылка, &Артикул)";

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

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

Запрос.Выполнить;

КонецЦикла;

// 3. Используем временную таблицу в основном запросе

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

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

"ВЫБРАТЬ

| ВТ_Товары.Ссылка КАК Товар,

| ДвиженияОстатков.КоличествоОстаток КАК Остаток

|ИЗ

| ВТ_Товары КАК ВТ_Товары

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

| ПО ВТ_Товары.Ссылка = ДвиженияОстатков.Товар

|ГДЕ

| ДвиженияОстатков.Период = &ДатаОтчета";

Запрос.УстановитьПараметр("ДатаОтчета", ТекущаяДата);

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

⚠️ Внимание: В PostgreSQL и IBM DB2 временные таблицы автоматически удаляются после завершения сеанса, а в Microsoft SQL Server — только при явном вызове УНИЧТОЖИТЬ ВТ_ИмяТаблицы. Всегда очищайте временные таблицы после использования, чтобы избежать накопления мусора в базе.
📊 Какой СУБД вы используете с 1С?
Microsoft SQL Server
PostgreSQL
IBM DB2
Oracle
Другая

2. Преобразование таблицы в массив структур: простой, но ограниченный способ

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

  • 📌 Ограничение 1: Максимальный размер параметра — 4 000 символов (в 1С:Предприятие 8.3.20+ расширен до 10 000). При превышении возникнет ошибка Длина параметра превышает допустимое значение.
  • 📌 Ограничение 2: Производительность падает экспоненциально при росте объема данных. Например, обработка 1 000 строк может занять в 10 раз дольше, чем при использовании временных таблиц.
  • 🔄 Когда применять: Для небольших таблиц (до 100–200 строк) в простых запросах.

Пример кода:

ТаблицаТоваров = ПолучитьТаблицуТоваров;

МассивСтруктур = Новый Массив;

// Преобразуем таблицу в массив структур

Для Каждого Строка Из ТаблицаТоваров Цикл

СтруктураСтроки = Новый Структура;

СтруктураСтроки.Вставить("Ссылка", Строка.Ссылка);

СтруктураСтроки.Вставить("Артикул", Строка.Артикул);

МассивСтруктур.Добавить(СтруктураСтроки);

КонецЦикла;

// Передаем массив как параметр

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

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

"ВЫБРАТЬ

| Товары.Артикул КАК Артикул,

| Товары.Наименование КАК Наименование

|ИЗ

| Справочник.Товары КАК Товары

|ГДЕ

| Товары.Артикул В (&Артикулы)";

Запрос.УстановитьПараметр("Артикулы", МассивСтруктур.ВыгрузитьКолонку("Артикул"));

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

💡

Если нужно передать несколько колонок, используйте функцию ЗначениеВМассивJSON (доступна с версии 8.3.18). Она позволяет сериализовать структуру в строку и избежать ограничения на длину параметра. Пример: Запрос.УстановитьПараметр("Данные", ЗначениеВМассивJSON(МассивСтруктур));

3. Динамические списки: альтернатива для отчетов и выборок

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

  • 📊 Отображения данных в отчетах с фильтрами.
  • 🔍 Поиска по справочникам с динамической выборкой.
  • 📋 Формирования списков документов по критериям из таблицы.

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

// Создаем динамический список

ДинамическийСписок = Документы.ЗаказыПокупателей.СоздатьМенеджерВыбора;

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

// Добавляем отбор по товарам из таблицы

ТаблицаТоваров = ПолучитьТаблицуТоваров;

Для Каждого Строка Из ТаблицаТоваров Цикл

ДинамическийСписок.ПараметрыВыбора.Отбор.Добавить("Товары.Ссылка", Тип("Равно"), Строка.Ссылка, Истина);

КонецЦикла;

// Получаем результат

Результат = ДинамическийСписок.ВыполнитьВыбор;

⚠️ Внимание: Динамические списки не поддерживают сложные соединения таблиц (например, LEFT JOIN с несколькими условиями). Для таких случаев используйте временные таблицы или массивы структур.

4. Сравнение методов: какой выбрать для вашей задачи

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

Критерий Временные таблицы Массив структур Динамические списки
Макс. объем данных Неограниченно До 10 000 строк* До 10 000 строк
Производительность ⭐⭐⭐⭐⭐ ⭐⭐ ⭐⭐⭐
Сложность реализации Средняя Низкая Низкая
Поддержка в файловом варианте Нет Да Да
Требуемые права CREATE TABLE Нет Нет

* В версиях 1С ниже 8.3.20 ограничение — 4 000 символов на параметр.

💡

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

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

Даже при правильном выборе метода передачи таблицы в запрос можно столкнуться с проблемами производительности. Вот 5 практических советов для оптимизации:

  1. Индексируйте временные таблицы. Если временная таблица используется в соединениях (JOIN), добавьте индекс по ключевым полям:
    СОЗДАТЬ ИНДЕКС IX_ВТ_Товары_Ссылка НА ВТ_Товары(Ссылка)
  2. Используйте пакетную вставку. Вместо цикла по строкам загружайте данные пакетами по 1 000–5 000 строк:
    Запрос.Текст ="ВСТАВИТЬ В ВТ_Товары ВЫБРАТЬ * ИЗ &Таблица";
    

    Запрос.УстановитьПараметр("Таблица", ТаблицаТоваров.Выгрузить);

  3. Ограничивайте колонки. Передавайте в запрос только необходимые поля таблицы, чтобы уменьшить объем данных.
  4. Избегайте LIKE с параметрами. Фильтрация по шаблону (ПОДОБНО) с табличными параметрами работает крайне медленно.
  5. Тестируйте на реальных данных. Производительность может отличаться в 100 раз в зависимости от СУБД и версии 1С.

Используются ли индексы на временных таблицах?|

Передаются только необходимые колонки?|

Данные загружаются пакетами, а не построчно?|

Отсутствуют операции LIKE/PODOBNO с параметрами?|

Тестировался ли запрос на объеме данных > 10 000 строк?

-->

6. Типичные ошибки и как их избежать

При работе с таблицами в запросах разработчики часто сталкиваются с одними и теми же проблемами. Вот топ-3 ошибки и способы их решения:

  • 🚫 Ошибка 1: Поле объекта не обнаружено (&Параметр)

    Причина: Несовпадение имен колонок в таблице значений и параметрах запроса.

    Решение: Проверьте регистр и названия колонок. В 1С имена параметров чувствительны к регистру!

  • 🚫 Ошибка 2: Превышен максимальный размер параметра

    Причина: Передача слишком большого массива структур (более 10 000 строк).

    Решение: Разбейте данные на части или используйте временные таблицы.

  • 🚫 Ошибка 3: Запрос выполняется крайне медленно без видимых причин.

    Причина: Отсутствие индексов на временных таблицах или неоптимальный план выполнения.

    Решение: Проанализируйте план запроса в Консоли запросов 1С (меню Все функции → План запроса).

Как включить отображение плана запроса в 1С 8.3

1. Откройте консоль запросов (Ctrl+Shift+Q).

2. В меню выберите Все функции → Показать план запроса.

3. Выполните запрос — план отобразится в отдельной вкладке.

4. Обратите внимание на узкие места (операции TABLE SCAN или NESTED LOOP без индексов).

7. Примеры реальных задач с табличными параметрами

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

Задача 1: Формирование отчета по остаткам товаров из Excel.

Пользователь загружает в 1С таблицу с артикулами из Excel и хочет получить остатки только по этим товарам. Решение:

// 1. Чтение данных из Excel

ТаблицаАртикулов = ПрочитатьExcelФайл(ПутьКФайлу);

// 2. Создание временной таблицы

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

Запрос.Текст ="ВЫБРАТЬ Артикул ПОМЕСТИТЬ ВТ_Артикулы ИЗ &Таблица";

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

Запрос.Выполнить;

// 3. Запрос остатков

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

"ВЫБРАТЬ

| ВТ_Артикулы.Артикул КАК Артикул,

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

|ИЗ

| ВТ_Артикулы КАК ВТ_Артикулы

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

| ПО ВТ_Артикулы.Артикул = Остатки.Товар.Артикул";

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

Задача 2: Синхронизация данных с внешней системой.

При интеграции с 1С:EDT или REST API часто требуется передать список измененных объектов. Пример для документов ЗаказПокупателя:

// 1. Получаем список измененных заказов из внешней системы

СписокЗаказов = ПолучитьИзмененныеЗаказыИзAPI;

// 2. Преобразуем в массив GUID

МассивGUID = Новый Массив;

Для Каждого Заказ Из СписокЗаказов Цикл

МассивGUID.Добавить(Заказ.УникальныйИдентификатор);

КонецЦикла;

// 3. Запрашиваем данные по этим GUID

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

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

"ВЫБРАТЬ

| Заказы.Ссылка КАК Ссылка,

| Заказы.Номер КАК Номер

|ИЗ

| Документ.ЗаказПокупателя КАК Заказы

|ГДЕ

| Заказы.УникальныйИдентификатор В (&GUIDs)";

Запрос.УстановитьПараметр("GUIDs", МассивGUID);

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

FAQ: Частые вопросы по работе с таблицами в запросах 1С

Можно ли передать табличную часть документа напрямую в запрос?

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

ТабличнаяЧасть = Документ.Товары;

МассивДанных = ТабличнаяЧасть.Выгрузить;

Как передать таблицу с более чем 10 000 строк в файловом варианте 1С?

В файловом варианте временные таблицы недоступны, а массив структур ограничен 10 000 элементами. Решения:

  1. Разбить данные на части и выполнить несколько запросов.
  2. Использовать внешние обработки с SQLite для промежуточного хранения.
  3. Оптимизировать задачу так, чтобы фильтрация происходила на стороне 1С, а не в запросе.
Почему запрос с временной таблицей работает медленно?

Частые причины:

  • Отсутствуют индексы на временной таблице.
  • Данные загружаются построчно, а не пакетами.
  • СУБД не использует оптимальный план выполнения (проверьте в План запроса).
  • Временная таблица создается в транзакции, что блокирует другие процессы.

Решение: добавьте индексы, используйте пакетную вставку и анализируйте план запроса.

Можно ли использовать табличные параметры в управляемых формах?

Да, но с ограничениями:

  • Временные таблицы требуют серверного контекста (используйте в модуле объекта или на сервере).
  • Массивы структур можно передавать и на клиенте, но объем данных ограничен.
  • Для динамических списков в управляемых формах используйте метод УстановитьПараметр менеджера выбора.
Как передать таблицу в запрос с группировкой (GROUP BY)?

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

// 1. Создаем временную таблицу с категориями товаров

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

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

"ВЫБРАТЬ

| Категория КАК Категория,

| СУММА(Количество) КАК ОбщееКоличество

|ИЗ

| ВТ_Товары КАК ВТ_Товары

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

| ПО ВТ_Товары.Ссылка = Остатки.Товар

|СГРУППИРОВАТЬ ПО

| Категория";