При разработке на платформе 1С:Предприятие 8 часто возникает задача перенести данные, полученные из базы данных с помощью запроса, в массив для их дальнейшей обработки, передачи в параметры другого запроса или вывода пользователю. Чтобы код соответствовал принятым нормам, рекомендуется использовать проверенные шаблоны для применения стандартов и методик разработки конфигураций 1С. Несмотря на кажущуюся простоту, здесь существует несколько подходов, каждый из которых имеет свои преимущества, недостатки и скрытые "подводные камни". Рассмотрим подробнее, как это сделать правильно, и какие ошибки чаще всего допускают разработчики.
Это самый быстрый и лаконичный способ получения массива данных, если нам нужно извлечь значения только одного конкретного поля. Рассмотрим ситуацию, когда мы уже выполнили запрос и получили объект РезультатЗапроса. Подобный подход упрощает работу разработчика и аналитика при написании запросов в 1С, позволяя избежать лишних циклов — для этого удобно использовать консоль запросов и кода для разработчиков 1С.
Проанализируем пример кода:
// Выполняем запрос
Результат = Запрос.Выполнить();
// Выгружаем результат в таблицу значений
ТаблицаРезультата = Результат.Выгрузить();
// Получаем массив значений из конкретной колонки
МассивЗначений = ТаблицаРезультата.ВыгрузитьКолонку("ИмяКолонки");
Разберем по шагам, что здесь происходит. Метод Выгрузить() преобразует весь результат запроса в объект ТаблицаЗначений. Затем метод таблицы ВыгрузитьКолонку() берет все данные из указанного столбца и упаковывает их в массив. Это решение является наиболее популярным в типовых конфигурациях, таких как 1С:ERP или 1С:УТ 11.
Важный нюанс: Вы можете обращаться к колонке не только по имени, но и по индексу. Это полезно, если вы хотите избежать "хардкода" имен колонок в коде или если имя колонки формируется динамически.
// Выгрузка первой колонки (индекс 0)
МассивЗначений = Результат.Выгрузить().ВыгрузитьКолонку(0);
Иногда использование Выгрузить() нежелательно. Специалисты, проводящие анализ и автоматическое редактирование модулей, часто указывают на то, что создание промежуточной таблицы значений неоправданно расходует оперативную память, особенно если результат запроса содержит десятки или сотни тысяч строк. В этом случае мы используем прямой обход выборки.
Рассмотрим правильную реализацию через цикл:
МассивРезультатов = Новый Массив;
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
МассивРезультатов.Добавить(Выборка.ИмяПоля);
КонецЦикла;
Этот метод работает медленнее, так как код исполняется интерпретатором встроенного языка 1С, в то время как ВыгрузитьКолонку() работает на уровне платформенного C++ кода. Однако с точки зрения потребления памяти выборка эффективнее, так как она не создает дубликат данных всего запроса в памяти сервера.
Выясним причину одной из самых коварных ошибок начинающих программистов. Этот вопрос часто затрагивает методический материал для собеседования, помогая выявить уровень понимания работы объектов платформы. Посмотрим на пример кода, который категорически нельзя использовать:
// ОШИБОЧНЫЙ КОД
МассивСтрок = Новый Массив;
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
// Ошибка! Мы добавляем сам объект выборки
МассивСтрок.Добавить(Выборка);
КонецЦикла;
Почему этот код не работает? Объект ВыборкаИзРезультатаЗапроса — это курсор, который перемещается по записям. Когда вы вызываете Добавить(Выборка), в массив добавляется не копия текущей строки, а ссылка на сам объект выборки. В итоге, после завершения цикла, вы получите массив, заполненный одинаковыми элементами, указывающими на последнюю строку — быстро выявлять такие ошибки поможет инструмент пошаговой отладки кода 1С.
Если вам нужно сохранить в массив не одно значение, а всю строку целиком (со всеми колонками), необходимо на каждой итерации "разрывать" связь с курсором выборки. Чтобы исключить подобные недочеты, полезно проводить автоматический анализ конфигураций на наличие ошибок, связанных с неправильной обработкой данных.
Рассмотрим пример правильного сохранения строк:
МассивСтруктур = Новый Массив;
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
НоваяСтрока = Новый Структура;
// Заполняем структуру данными текущей строки
Для каждого Колонка Из Результат.Колонки Цикл
НоваяСтрока.Вставить(Колонка.Имя, Выборка[Колонка.Имя]);
КонецЦикла;
МассивСтруктур.Добавить(НоваяСтрока);
КонецЦикла;
Для упрощения кода и повышения производительности можно использовать функцию ЗаполнитьЗначенияСвойств():
Пока Выборка.Следующий() Цикл
СтруктураДанных = Новый Структура("Артикул, Цена, Количество");
ЗаполнитьЗначенияСвойств(СтруктураДанных, Выборка);
МассивСтруктур.Добавить(СтруктураДанных);
КонецЦикла;
Проанализируем ситуацию с точки зрения ресурсов сервера. Выбор между Выгрузить() и обходом выборки зависит от объема данных:
ВыгрузитьКолонку(). Это быстро, лаконично и легко читается.rphost.Часто массив нужен для того, чтобы собрать уникальные ссылки. Если в исходном запросе могут быть дубли, у вас есть два пути:
РАЗЛИЧНЫЕ в самом тексте запроса.Соответствие для сбора уникальных ключей, а затем перенесите ключи соответствия в массив.Пример с Соответствие:
УникальныеЗначения = Новый Соответствие;
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
// Ключ соответствия всегда уникален
УникальныеЗначения.Вставить(Выборка.Ссылка, Истина);
КонецЦикла;
// Получаем массив уникальных ключей
МассивУникальных = Новый Массив;
Для каждого КлючИЗначение Из УникальныеЗначения Цикл
МассивУникальных.Добавить(КлючИЗначение.Ключ);
КонецЦикла;
Важно помнить, что если в результате запроса образовалось значение NULL, оно попадет в ваш массив именно в таком виде. Это может вызвать ошибку при сравнении. Всегда обрабатывайте потенциальные NULL в тексте запроса с помощью функции ЕстьNULL().
Если ваша цель — выгрузить данные в массив, чтобы передать его как параметр в другой запрос, помните об ограничениях СУБД. При больших объемах эффективнее использовать временные таблицы. К слову, в современных версиях платформы стало доступно добавление данных в существующую временную таблицу, что открывает новые возможности для оптимизации сложных алгоритмов без использования промежуточных массивов на стороне сервера приложений.