Читайте дальше...
Базовый пакетный запрос с параметрами
// Пакетный запрос: выполнение нескольких запросов в одном пакете
Процедура ВыполнитьПакетныйЗапрос()
Пакет = Новый ПакетЗапросов;
// Добавляем первый запрос
Запрос1 = Пакет.Добавить("ВЫБРАТЬ КОЛИЧЕСТВО(*) КАК КолИЗ Справочник.Номенклатура");
// Добавляем второй запрос
Запрос2 = Пакет.Добавить("ВЫБРАТЬ КОЛИЧЕСТВО(*) КАК КолИЗ Справочник.Контрагенты");
// Добавляем третий запрос
Запрос3 = Пакет.Добавить("ВЫБРАТЬ СУММА(Сумма) КАК ОбщаяСумма ИЗ Документ.РеализацияТоваров");
// Выполняем пакет
Результаты = Пакет.Выполнить();
// Получаем результаты
Выборка1 = Результаты[0].Выбрать();
Выборка1.Следующий();
Сообщить("Количество номенклатуры: " + Выборка1.Кол);
Выборка2 = Результаты[1].Выбрать();
Выборка2.Следующий();
Сообщить("Количество контрагентов: " + Выборка2.Кол);
Выборка3 = Результаты[2].Выбрать();
Выборка3.Следующий();
Сообщить("Общая сумма реализации: " + Выборка3.ОбщаяСумма);
КонецПроцедуры
Пакетный запрос с использованием временных таблиц
// Пакетные запросы с обменом данными через временные таблицы
Процедура ПакетныйЗапросСВременнымиТаблицами()
Пакет = Новый ПакетЗапросов;
Пакет.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
// Запрос 1: создаем временную таблицу дорогих товаров
Пакет.Добавить("
|ВЫБРАТЬ
| Номенклатура.Ссылка КАК Товар,
| Номенклатура.Наименование КАК Наименование,
| Номенклатура.Цена КАК Цена
|ПОМЕСТИТЬ ВТ_ДорогиеТовары
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Цена > 10000");
// Запрос 2: используем временную таблицу для анализа продаж
Пакет.Добавить("
|ВЫБРАТЬ
| ВТ_ДорогиеТовары.Наименование,
| ВТ_ДорогиеТовары.Цена,
| СУММА(Продажи.Сумма) КАК СуммаПродаж
|ИЗ
| ВТ_ДорогиеТовары КАК ВТ_ДорогиеТовары
| ЛЕВОЕ СОЕДИНЕНИЕ Документ.РеализацияТоваров.Товары КАК Продажи
| ПО ВТ_ДорогиеТовары.Товар = Продажи.Номенклатура
|СГРУППИРОВАТЬ ПО
| ВТ_ДорогиеТовары.Наименование,
| ВТ_ДорогиеТовары.Цена");
// Запрос 3: итоговый отчет
Пакет.Добавить("
|ВЫБРАТЬ
| СУММА(СуммаПродаж) КАК ИтоговаяСумма,
| КОЛИЧЕСТВО(*) КАК КоличествоТоваров
|ИЗ
| ВТ_ДорогиеТовары");
Результаты = Пакет.Выполнить();
// Выводим результат второго запроса
Выборка2 = Результаты[1].Выбрать();
Сообщить("Продажи дорогих товаров:");
Пока Выборка2.Следующий() Цикл
Сообщить(Выборка2.Наименование + " (цена " + Выборка2.Цена + "): продано на " + Выборка2.СуммаПродаж);
КонецЦикла;
// Выводим итог
Выборка3 = Результаты[2].Выбрать();
Выборка3.Следующий();
Сообщить("Итого по дорогим товарам: " + Выборка3.КоличествоТоваров +
" товаров на сумму " + Выборка3.ИтоговаяСумма);
КонецПроцедуры
Динамическое построение пакетного запроса
// Построение пакетного запроса на основе массива условий
Функция ПостроитьПакетныйЗапросПоМассиву(МассивНоменклатуры)
Пакет = Новый ПакетЗапросов;
МенеджерВТ = Новый МенеджерВременныхТаблиц;
Пакет.МенеджерВременныхТаблиц = МенеджерВТ;
// Создаем временную таблицу с переданными товарами
ЗапросСоздания = Новый Запрос;
ЗапросСоздания.Текст = "
|ВЫБРАТЬ
| &Товар КАК Товар
|ПОМЕСТИТЬ ВТ_СписокТоваров";
ЗапросСоздания.УстановитьПараметр("Товар", МассивНоменклатуры);
Пакет.Добавить(ЗапросСоздания.Текст);
// Для каждого товара создаем отдельный запрос в пакете
Для Каждого Товар Из МассивНоменклатуры Цикл
ТекстЗапроса = "
|ВЫБРАТЬ
| &Товар КАК Товар,
| СУММА(Остатки.Количество) КАК Остаток
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки(&ДатаОтчета, Товар = &Товар) КАК Остатки";
Запрос = Пакет.Добавить(ТекстЗапроса);
Запрос.УстановитьПараметр("Товар", Товар);
КонецЦикла;
Возврат Пакет;
КонецФункции
// Пример использования
Процедура ПолучитьОстаткиПоСпискуТоваров()
// Подготавливаем массив товаров
МассивТоваров = Новый Массив;
МассивТоваров.Добавить(Справочники.Номенклатура.НайтиПоНаименованию("Ноутбук"));
МассивТоваров.Добавить(Справочники.Номенклатура.НайтиПоНаименованию("Монитор"));
МассивТоваров.Добавить(Справочники.Номенклатура.НайтиПоНаименованию("Клавиатура"));
// Создаем и выполняем пакет
Пакет = ПостроитьПакетныйЗапросПоМассиву(МассивТоваров);
// Устанавливаем общие параметры для всех запросов пакета
Пакет.УстановитьПараметр("ДатаОтчета", ТекущаяДата());
Результаты = Пакет.Выполнить();
// Обрабатываем результаты
Для Инд = 0 По Результаты.Количество() - 1 Цикл
Выборка = Результаты[Инд].Выбрать();
Пока Выборка.Следующий() Цикл
Сообщить("Товар: " + Выборка.Товар + ", остаток: " + Выборка.Остаток);
КонецЦикла;
КонецЦикла;
КонецПроцедуры
Пакетный запрос с условным выполнением
// Выполнение разных запросов в пакете в зависимости от условий
Процедура ПакетныйЗапросСУсловиями()
Пакет = Новый ПакетЗапросов;
ДатаОтчета = КонецМесяца(ТекущаяДата());
// Базовый запрос - получение списка складов
ЗапросСклады = Пакет.Добавить("
|ВЫБРАТЬ
| Склады.Ссылка КАК Склад,
| Склады.Наименование КАК Наименование
|ИЗ
| Справочник.Склады КАК Склады");
// Условные запросы для каждого склада
ЗапросыПоСкладам = Новый Соответствие;
// Получаем список складов
ВыборкаСкладов = Пакет.Выполстить()[0].Выбрать();
Пока ВыборкаСкладов.Следующий() Цикл
// Для каждого склада добавляем запрос в пакет
ТекстЗапроса = "
|ВЫБРАТЬ
| Остатки.Номенклатура,
| СУММА(Остатки.Количество) КАК Остаток
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки(&ДатаОтчета, Склад = &Склад) КАК Остатки
|СГРУППИРОВАТЬ ПО
| Остатки.Номенклатура";
ДобавленныйЗапрос = Пакет.Добавить(ТекстЗапроса);
ДобавленныйЗапрос.УстановитьПараметр("Склад", ВыборкаСкладов.Склад);
ЗапросыПоСкладам.Вставить(ВыборкаСкладов.Склад, ДобавленныйЗапрос);
КонецЦикла;
// Устанавливаем общий параметр
Пакет.УстановитьПараметр("ДатаОтчета", ДатаОтчета);
// Выполняем пакет
Результаты = Пакет.Выполнить();
// Обрабатываем результаты каждого склада
НомерЗапроса = 1; // 0 - запрос складов
Для Каждого КлючЗначение Из ЗапросыПоСкладам Цикл
Склад = КлючЗначение.Ключ;
Выборка = Результаты[НомерЗапроса].Выбрать();
Сообщить("Остатки по складу " + Склад + ":");
Пока Выборка.Следующий() Цикл
Сообщить(" " + Выборка.Номенклатура + ": " + Выборка.Остаток);
КонецЦикла;
НомерЗапроса = НомерЗапроса + 1;
КонецЦикла;
КонецПроцедуры
Пакетный запрос с обработкой ошибок
// Выполнение пакетного запроса с изоляцией ошибок
Функция ВыполнитьПакетныйЗапросБезопасно(Пакет)
Результаты = Новый Массив;
Ошибки = Новый Массив;
Для Инд = 0 По Пакет.Количество() - 1 Цикл
// Создаем отдельный пакет для каждого запроса
ВременныйПакет = Новый ПакетЗапросов;
Запрос = Пакет.Получить(Инд);
// Копируем менеджер временных таблиц, если есть
Если Пакет.МенеджерВременныхТаблиц <> Неопределено Тогда
ВременныйПакет.МенеджерВременныхТаблиц = Пакет.МенеджерВременныхТаблиц;
КонецЕсли;
// Копируем текст запроса и параметры
ДобавленныйЗапрос = ВременныйПакет.Добавить(Запрос.Текст);
Для Каждого Парам Из Запрос.Параметры Цикл
ДобавленныйЗапрос.УстановитьПараметр(Парам.Ключ, Парам.Значение);
КонецЦикла;
Попытка
Результат = ВременныйПакет.Выполнить();
Результаты.Добавить(Результат[0]);
Ошибки.Добавить(Неопределено);
Исключение
Результаты.Добавить(Неопределено);
Ошибки.Добавить(ОписаниеОшибки());
КонецПопытки;
КонецЦикла;
// Формируем результат
СтруктураРезультата = Новый Структура;
СтруктураРезультата.Вставить("Результаты", Результаты);
СтруктураРезультата.Вставить("Ошибки", Ошибки);
СтруктураРезультата.Вставить("УспешноВыполнено",
Результаты.Найти(Неопределено) = Неопределено ? Результаты.Количество() :
Массив.Количество(Результаты, Неопределено, Истина));
Возврат СтруктураРезультата;
КонецФункции
// Пример использования
Процедура ТестБезопасногоПакета()
Пакет = Новый ПакетЗапросов;
// Корректный запрос
Пакет.Добавить("ВЫБРАТЬ ПЕРВЫЕ 5 * ИЗ Справочник.Номенклатура");
// Ошибочный запрос (несуществующая таблица)
Пакет.Добавить("ВЫБРАТЬ * ИЗ НесуществующийСправочник");
// Корректный запрос
Пакет.Добавить("ВЫБРАТЬ КОЛИЧЕСТВО(*) КАК КолИЗ Справочник.Контрагенты");
Результат = ВыполнитьПакетныйЗапросБезопасно(Пакет);
Сообщить("Успешно выполнено: " + Результат.УспешноВыполнено +
" из " + Строка(Пакет.Количество()));
Для Инд = 0 По Результат.Результаты.Количество() - 1 Цикл
Если Результат.Ошибки[Инд] <> Неопределено Тогда
Сообщить("Ошибка в запросе " + Строка(Инд) + ": " + Результат.Ошибки[Инд]);
Иначе
Сообщить("Запрос " + Строка(Инд) + " выполнен успешно");
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Пакетный запрос с итоговыми агрегациями
// Использование пакетных запросов для многоуровневой агрегации
Процедура МногоуровневаяАгрегация()
Пакет = Новый ПакетЗапросов;
Пакет.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
// Уровень 1: продажи по дням
Пакет.Добавить("
|ВЫБРАТЬ
| ВЫРАЗИТЬ(Продажи.Период КАК ДАТА) КАК Дата,
| СУММА(Продажи.Сумма) КАК СуммаДня
|ПОМЕСТИТЬ ВТ_ПродажиПоДням
|ИЗ
| Документ.РеализацияТоваров КАК Продажи
|ГДЕ
| Продажи.Период МЕЖДУ &ДатаНачала И &ДатаОкончания
|СГРУППИРОВАТЬ ПО
| ВЫРАЗИТЬ(Продажи.Период КАК ДАТА)");
// Уровень 2: продажи по неделям
Пакет.Добавить("
|ВЫБРАТЬ
| НАЧАЛОНЕДЕЛИ(ПродажиПоДням.Дата) КАК Неделя,
| СУММА(ПродажиПоДням.СуммаДня) КАК СуммаНедели
|ПОМЕСТИТЬ ВТ_ПродажиПоНеделям
|ИЗ
| ВТ_ПродажиПоДням КАК ПродажиПоДням
|СГРУППИРОВАТЬ ПО
| НАЧАЛОНЕДЕЛИ(ПродажиПоДням.Дата)");
// Уровень 3: продажи по месяцам
Пакет.Добавить("
|ВЫБРАТЬ
| НАЧАЛОМЕСЯЦА(ПродажиПоНеделям.Неделя) КАК Месяц,
| СУММА(ПродажиПоНеделям.СуммаНедели) КАК СуммаМесяца
|ПОМЕСТИТЬ ВТ_ПродажиПоМесяцам
|ИЗ
| ВТ_ПродажиПоНеделям КАК ПродажиПоНеделям
|СГРУППИРОВАТЬ ПО
| НАЧАЛОМЕСЯЦА(ПродажиПоНеделям.Неделя)");
// Финальный запрос: все уровни вместе
Пакет.Добавить("
|ВЫБРАТЬ
| ПоДням.Дата,
| ПоДням.СуммаДня,
| ПоНеделям.Неделя,
| ПоНеделям.СуммаНедели,
| ПоМесяцам.Месяц,
| ПоМесяцам.СуммаМесяца
|ИЗ
| ВТ_ПродажиПоДням КАК ПоДням
| ЛЕВОЕ СОЕДИНЕНИЕ ВТ_ПродажиПоНеделям КАК ПоНеделям
| ПО НАЧАЛОНЕДЕЛИ(ПоДням.Дата) = ПоНеделям.Неделя
| ЛЕВОЕ СОЕДИНЕНИЕ ВТ_ПродажиПоМесяцам КАК ПоМесяцам
| ПО НАЧАЛОМЕСЯЦА(ПоДням.Дата) = ПоМесяцам.Месяц
|УПОРЯДОЧИТЬ ПО
| ПоДням.Дата");
Пакет.УстановитьПараметр("ДатаНачала", НачалоМесяца(ТекущаяДата())-45);
Пакет.УстановитьПараметр("ДатаОкончания", ТекущаяДата());
Результаты = Пакет.Выполнить();
Выборка = Результаты[3].Выбрать(); // Финальный результат
Сообщить("Агрегированные продажи:");
Пока Выборка.Следующий() Цикл
Сообщить(Выборка.Дата + " | День: " + Выборка.СуммаДня +
" | Неделя: " + Выборка.СуммаНедели +
" | Месяц: " + Выборка.СуммаМесяца);
КонецЦикла;
КонецПроцедуры
Пакетный запрос с динамическими параметрами
// Пакетный запрос с установкой параметров из внешнего источника
Процедура ПакетныйЗапросСДинамическимиПараметрами()
// Источник параметров (например, таблица значений)
ПараметрыОтчета = Новый ТаблицаЗначений;
ПараметрыОтчета.Колонки.Добавить("НаименованиеПараметра");
ПараметрыОтчета.Колонки.Добавить("Значение");
ПараметрыОтчета.Добавить().НаименованиеПараметра = "ДатаНачала";
ПараметрыОтчета[0].Значение = НачалоГода(ТекущаяДата());
ПараметрыОтчета.Добавить().НаименованиеПараметра = "ДатаОкончания";
ПараметрыОтчета[1].Значение = КонецГода(ТекущаяДата());
ПараметрыОтчета.Добавить().НаименованиеПараметра = "Склад";
ПараметрыОтчета[2].Значение = Справочники.Склады.НайтиПоНаименованию("Основной склад");
ПараметрыОтчета.Добавить().НаименованиеПараметра = "МинимальнаяСумма";
ПараметрыОтчета[3].Значение = 10000;
// Формируем пакетный запрос
Пакет = Новый ПакетЗапросов;
Пакет.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
Пакет.Добавить("
|ВЫБРАТЬ
| Реализация.Контрагент,
| СУММА(Реализация.Сумма) КАК ОбщаяСумма
|ПОМЕСТИТЬ ВТ_ПродажиПоКонтрагентам
|ИЗ
| Документ.РеализацияТоваров КАК Реализация
|ГДЕ
| Реализация.Период МЕЖДУ &ДатаНачала И &ДатаОкончания
| И Реализация.Склад = &Склад
|СГРУППИРОВАТЬ ПО
| Реализация.Контрагент");
Пакет.Добавить("
|ВЫБРАТЬ
| ВТ_ПродажиПоКонтрагентам.Контрагент,
| ВТ_ПродажиПоКонтрагентам.ОбщаяСумма
|ИЗ
| ВТ_ПродажиПоКонтрагентам КАК ВТ_ПродажиПоКонтрагентам
|ГДЕ
| ВТ_ПродажиПоКонтрагентам.ОбщаяСумма >= &МинимальнаяСумма
|УПОРЯДОЧИТЬ ПО
| ОбщаяСумма УБЫВ");
// Устанавливаем параметры из таблицы
Для Каждого СтрокаПараметра Из ПараметрыОтчета Цикл
Пакет.УстановитьПараметр(СтрокаПараметра.НаименованиеПараметра, СтрокаПараметра.Значение);
КонецЦикла;
// Дополнительная проверка перед выполнением
Попытка
Результаты = Пакет.Выполнить();
Выборка = Результаты[1].Выбрать();
Сообщико("Контрагенты с суммой продаж более " +
Строка(ПараметрыОтчета[3].Значение) + ":");
Пока Выборка.Следующий() Цикл
Сообщить(Выборка.Контрагент + " - " + Выборка.ОбщаяСумма);
КонецЦикла;
Исключение
Сообщить("Ошибка выполнения пакетного запроса: " + ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
Пакетный запрос с INSERT и UPDATE
// Пакетное выполнение модифицирующих запросов
Процедура ПакетныйЗапросСМодификациейДанных()
Пакет = Новый ПакетЗапросов;
// Запрос 1: создаем временную таблицу
Пакет.Добавить("
|ВЫБРАТЬ
| Номенклатура.Ссылка КАК Товар,
| Номенклатура.Цена * 1.1 КАК НоваяЦена
|ПОМЕСТИТЬ ВТ_НовыеЦены
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.ЭтоГруппа = ЛОЖЬ
| И Номенклатура.Цена > 0");
// Запрос 2: обновляем цены (имитация через запрос, если поддерживается)
// В некоторых конфигурациях можно использовать конструкцию ВЫБРАТЬ ... ПОМЕСТИТЬ ... ВРЕМЕННУЮ
Пакет.Добавить("
|// Обновление цен товаров на 10%
|ВЫБРАТЬ
| ВТ_НовыеЦены.Товар,
| ВТ_НовыеЦены.НоваяЦена
|ИЗ
| ВТ_НовыеЦены КАК ВТ_НовыеЦены");
// Запрос 3: выборка для проверки
Пакет.Добавить("
|ВЫБРАТЬ
| Номенклатура.Наименование,
| Номенклатура.Цена КАК СтараяЦена,
| ВТ_НовыеЦены.НоваяЦена
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_НовыеЦены КАК ВТ_НовыеЦены
| ПО Номенклатура.Ссылка = ВТ_НовыеЦены.Товар");
Пакет.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
Попытка
НачатьТранзакцию();
Результаты = Пакет.Выполнить();
// Выводим изменения
Выборка = Результаты[2].Выбрать();
Сообщить("Изменение цен:");
Пока Выборка.Следующий() Цикл
Сообщить(Выборка.Наименование + ": " + Выборка.СтараяЦена +
" -> " + Выборка.НоваяЦена);
КонецЦикла;
// Здесь должен быть код реального обновления данных
// (например, через Справочник.Номенклатура.ОбновитьЦены(ВТ_НовыеЦены))
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
Сообщить("Ошибка: " + ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
Пакетный запрос для разбиения данных на порции
// Разбиение большого запроса на пакетные порции для оптимизации
Функция ВыполнитьЗапросПорциями(ТекстЗапроса, РазмерПорции = 1000)
// Получаем общее количество записей
ЗапросСчетчик = Новый Запрос;
ЗапросСчетчик.Текст = СтрЗаменить(ТекстЗапроса, "ВЫБРАТЬ", "ВЫБРАТЬ КОЛИЧЕСТВО(*) КАК Всего");
РезультатСчетчик = ЗапросСчетчик.Выполнить();
Если РезультатСчетчик.Пустой() Тогда
Возврат Новый ТаблицаЗначений;
КонецЕсли;
ВыборкаСчетчик = РезультатСчетчик.Выбрать();
ВыборкаСчетчик.Следующий();
ВсегоЗаписей = ВыборкаСчетчик.Всего;
КоличествоПорций = Цел(ВсегоЗаписей / РазмерПорции) +
?(ВсегоЗаписей % РазмерПорции > 0, 1, 0);
// Создаем пакет запросов
Пакет = Новый ПакетЗапросов;
Для НомерПорции = 1 По КоличествоПорций Цикл
Смещение = (НомерПорции - 1) * РазмерПорции;
// Добавляем запрос с ограничением
ТекстПорции = ТекстЗапроса +
" ПРОПУСТИТЬ " + Строка(Смещение) +
" ПЕРВЫЕ " + Строка(РазмерПорции);
Пакет.Добавить(ТекстПорции);
КонецЦикла;
// Выполняем пакет
Результаты = Пакет.Выполнить();
// Объединяем все порции
ИтоговаяТаблица = Новый ТаблицаЗначений;
Для НомерПорции = 0 По Результаты.Количество() - 1 Цикл
ТаблицаПорции = Результаты[НомерПорции].Выгрузить();
Если ИтоговаяТаблица.Колонки.Количество() = 0 И ТаблицаПорции.Колонки.Количество() > 0 Тогда
// Копируем структуру из первой непустой порции
Для Каждого Колонка Из ТаблицаПорции.Колонки Цикл
ИтоговаяТаблица.Колонки.Добавить(Колонка.Имя, Колонка.ТипЗначения);
КонецЦикла;
КонецЕсли;
ИтоговаяТаблица.Объединить(ТаблицаПорции);
КонецЦикла;
Возврат ИтоговаяТаблица;
КонецФункции
// Пример использования
Процедура ОбработатьБольшойОбъемДанных()
ТекстБольшогоЗапроса = "
|ВЫБРАТЬ
| Номенклатура.Ссылка,
| Номенклатура.Наименование,
| Остатки.Количество,
| Остатки.Сумма
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(, ) КАК Остатки
| ПО Номенклатура.Ссылка = Остатки.Номенклатура";
// Выполняем порциями по 500 строк
Результат = ВыполнитьЗапросПорциями(ТекстБольшогоЗапроса, 500);
Сообщить("Всего обработано строк: " + Строка(Результат.Количество()));
// Дальнейшая обработка результата
// ...
КонецПроцедуры
Примечания
// Важные особенности работы с пакетными запросами:
// 1. Пакет запросов позволяет выполнить несколько запросов за одно обращение к СУБД
// 2. Все запросы в пакете выполняются в одной транзакции (если не настроено иное)
// 3. Временные таблицы доступны всем запросам пакета через общий МенеджерВременныхТаблиц
// 4. Параметры можно устанавливать как для всего пакета, так и для отдельных запросов
// 5. Результаты возвращаются в виде массива результатов запросов
// 6. При ошибке в одном запросе выполнение пакета прерывается
// 7. Для обработки ошибок изолированно используйте отдельные пакеты для каждого запроса
// 8. Пакетные запросы эффективны для ETL-операций и сложных отчетов
// 9. Количество запросов в пакете ограничено настройками СУБД (обычно достаточно 100-200)
// 10. При работе с большими объемами используйте порционную обработку через ПРОПУСТИТЬ и ПЕРВЫЕ








