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

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

Стандартный результат: ВыборкаДанных

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

Для работы с таким результатом необходимо использовать цикл Пока Выборка.Следующий(). Внутри цикла вы обращаетесь к полям запроса как к свойствам объекта выборки. Если в запросе использовались псевдонимы полей, именно они становятся именами свойств. Попытка обратиться к несуществующему полю вызовет ошибку выполнения, поэтому внимательность при именовании критична.

💡

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

Существует нюанс, связанный с пустыми результатами. Если запрос синтаксически верен, но в базе данных не нашлось ни одной записи, соответствующей условиям выборки, метод Выполнить() все равно вернет объект ВыборкаДанных. Он просто будет пустым, и первый вызов метода Следующий() вернет Ложь. Это частая ошибка: разработчики иногда ожидают получение значения Неопределено при отсутствии данных, но это не так.

Агрегация и скалярные значения

Ситуация кардинально меняется, если ваш запрос содержит только агрегатные функции (например, СУММА, КОЛИЧЕСТВО, МИНИМУМ) и не содержит группировки по другим полям. В таком случае запрос должен вернуть ровно одну строку с одним колонкой. Платформа интерпретирует это как запрос на получение единственного значения.

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

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

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

Запрос.Текст = "ВЫБРАТЬ СУММА(Остатки.Количество) КАК СуммаОстатков ИЗ РегистрНакопления.Остатки КАК Остатки";

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

// Результат здесь — это Число, а не ВыборкаДанных!

Сумма = Результат;

Что будет, если агрегатный запрос вернет пустую таблицу?

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

Необходимо быть крайне осторожным при работе с такими запросами. Если вы попытаетесь вызвать метод Следующий() у переменной, содержащей число или Неопределено, система выдаст критическую ошибку. Всегда проверяйте логику формирования запроса: есть ли группировка? Если есть — будет выборка. Если нет и есть агрегат — будет значение.

Запросы с группировкой и ТаблицаЗначений

Когда в запросе присутствует оператор СГРУППИРОВАТЬ ПО, даже если в списке выбранных полей есть агрегатные функции, результат выполнения всегда будет объектом ВыборкаДанных. Логика проста: группировка потенциально может породить множество строк результата (по одной на каждую уникальную группу), поэтому платформа не может свернуть их в одно скалярное значение.

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

  • 📊 ВыборкаДанных — потоковый объект для одноразового последовательного чтения.
  • 📑 ТаблицаЗначений — статическая коллекция строк в памяти, поддерживающая индексацию и поиск.
  • 🔄 ТаблицаСсылок — специализированный тип для работы с ссылками на документы или справочники (редко возвращается запросом напрямую, чаще конвертируется).

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

📊 Какой тип результата вы чаще всего обрабатываете в своих задачах?
ВыборкаДанных
ТаблицаЗначений
Скалярное значение
Неопределено

Специфический случай: значение Неопределено

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

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

⚠️ Внимание: Перед использованием результата агрегатного запроса в вычислениях всегда проверяйте его на равенство Неопределено. Иначе выражение вида Сумма + 10 вызовет ошибку выполнения при пустой базе.

Для корректной обработки такой ситуации рекомендуется использовать функцию ЗначениеЗаполнено() или явное сравнение. Если значение не заполнено, его следует заменить на ноль или другое значение по умолчанию, зависящее от бизнес-логики вашей конфигурации.

Влияние временных таблиц на результат

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

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

Тип последнего оператора Наличие агрегатов Наличие ГРУППИРОВАТЬ ПО Возвращаемый тип
ВЫБРАТЬ Нет Нет ВыборкаДанных
ВЫБРАТЬ Да Нет Значение (Число, Дата, Строка) или Неопределено
ВЫБРАТЬ Да/Нет Да ВыборкаДанных
ВЫБРАТЬ ... ПОМЕСТИТЬ Любой Любой Пустая выборка (данные не возвращаются)
💡

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

Обработка ошибок выполнения запроса

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

Также существуют логические ошибки, когда запрос выполняется успешно, но возвращает не те данные. Например, забытое соединение (ЛЕВОЕ СОЕДИНЕНИЕ вместо ВНУТРЕННЕЕ СОЕДИНЕНИЕ) может привести к появлению дублей или потере строк. В этом случае тип возвращаемого объекта будет корректным (ВыборкаДанных), но содержимое — ошибочным.

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

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

FAQ: Частые вопросы по результатам запросов

Почему запрос возвращает Неопределено, хотя я жду ноль?

Это происходит при использовании агрегатных функций (СУММА, КОЛИЧЕСТВО) без группировки, когда в выборку не попало ни одной строки. Агрегатная функция не может посчитать сумму от пустого множества и возвращает Неопределено. Используйте функцию ЕСТЬNULL(Выражение, 0) прямо в тексте запроса, чтобы избежать этого.

Можно ли получить сразу ТаблицуЗначений методом Выполнить()?

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

Что вернет запрос с оператором ИЗМЕНЕНИЕ?

Запросы на изменение данных (ИЗМЕНИТЬ, УДАЛИТЬ, ВСТАВИТЬ) не возвращают данных для чтения. Метод Выполнить() в таких случаях обычно возвращает количество обработанных строк (число) или просто завершается успешно без возвращаемого значения, пригодного для дальнейшей выборки.

Как проверить, пуста ли ВыборкаДанных?

Самый надежный способ — вызвать метод Следующий(). Если он вернет Ложь, значит выборка пуста. Свойства типа Пустая() у объекта ВыборкаДанных не существует, проверка осуществляется только через попытку перехода к первой записи.