Разработка и Конфигурация · 12 мин
1С запрос как строка: способы задать и изменить текст запроса в коде
Как задать текст запроса в 1С строкой: конструктор запроса, конкатенация, параметры, подмена таблиц и полей, типичные ошибки и примеры кода на встроенном языке.
Во встроенном языке 1С текст запроса — это обычная строка, которую разработчик присваивает свойству Текст объекта Запрос. Понимание того, как эта строка формируется, критично для динамических отчётов, универсальных обработок и ситуаций, где структура выборки зависит от условий, известных только в момент выполнения.
Тема «1С запрос как строка» обычно возникает в трёх ситуациях: нужно собрать текст запроса программно из нескольких частей, подставить в него имя таблицы или поля, которое нельзя передать параметром, либо преобразовать готовый запрос обратно в строку для анализа или модификации. Каждая из этих задач решается своими приёмами, и у каждого есть ограничения.
Ниже разобраны базовый синтаксис, многострочные литералы, конкатенация, безопасная подстановка фрагментов, работа со схемой запроса как альтернатива ручной сборке строки, а также типичные ошибки, из-за которых динамически собранный запрос падает или возвращает неверные данные.
Как устроен текст запроса в виде строки
Свойство Текст объекта Запрос имеет тип Строка. Это значит, что платформа не компилирует запрос в момент написания кода: проверка синтаксиса и обращение к базе данных происходят только при вызове Выполнить() или НайтиПараметры(). До этого момента текст — просто набор символов, с которым можно работать любыми строковыми функциями.
Из этого следуют два практических вывода. Во-первых, ошибку в динамически собранном тексте вы увидите только в момент выполнения, а не при проверке модуля конфигуратором. Во-вторых, текст можно свободно строить по частям, хранить в переменных, макетах, передавать между процедурами и менять перед выполнением.
Минимальный пример задания запроса строкой выглядит так:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка,
| Номенклатура.Наименование КАК Наименование
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| НЕ Номенклатура.ПометкаУдаления";
Результат = Запрос.Выполнить().Выбрать();
Многострочные строковые литералы и вертикальная черта
Основной способ записать запрос как строку прямо в коде — многострочный литерал. Во встроенном языке 1С строка, продолжающаяся на несколько строк, оформляется так: каждая новая строка начинается с символа вертикальной черты |, а весь литерал обрамляется двойными кавычками. Кавычка внутри такого текста удваивается ("").
Именно этот формат генерирует конструктор запроса, когда вы нажимаете «ОК» в режиме «запрос в виде строки». Отступы перед вертикальной чертой и после неё не влияют на содержимое: платформа отрезает служебные пробелы, поэтому текст можно выравнивать под структуру модуля.
Частая трудность — кавычки внутри текста запроса, например при сравнении со строковым литералом. Внутри многострочной строки их нужно удваивать: ГДЕ Товары.Страна = ""Россия"". Если кавычек много, удобнее вынести значение в параметр запроса — так код читается проще и исключаются ошибки экранирования.
Сборка текста запроса конкатенацией и СтрШаблон
Когда структура запроса зависит от условий, текст собирают из частей. Классический приём — базовый текст плюс условно добавляемые фрагменты:
ТекстЗапроса =
"ВЫБРАТЬ
| Продажи.Номенклатура КАК Номенклатура,
| СУММА(Продажи.СуммаОборот) КАК Сумма
|ИЗ
| РегистрНакопления.Продажи.Обороты(&Начало, &Конец, , ) КАК Продажи";
Если ГруппироватьПоСкладам Тогда
ТекстЗапроса = ТекстЗапроса + "
|СГРУППИРОВАТЬ ПО
| Продажи.Номенклатура,
| Продажи.Склад";
Иначе
ТекстЗапроса = ТекстЗапроса + "
|СГРУППИРОВАТЬ ПО
| Продажи.Номенклатура";
КонецЕсли;
Запрос = Новый Запрос(ТекстЗапроса);
Для точечных подстановок удобна функция СтрШаблон: она заменяет маркеры %1, %2 и так далее на переданные значения. Так удобно подставлять имя таблицы, поля или вида сравнения:
ТекстЗапроса = СтрШаблон(
"ВЫБРАТЬ Таблица.Ссылка ИЗ Справочник.%1 КАК Таблица
|ГДЕ Таблица.%2 = &Значение",
ИмяСправочника,
ИмяРеквизита);
Помните про порядок: сначала текст полностью собирается, потом присваивается запросу, затем устанавливаются параметры и только после этого вызывается Выполнить(). Установка параметров до присвоения текста — частая причина ошибки «переменная не определена».
- 1Сформируйте полный текст запроса строкой: литерал, конкатенация или СтрШаблон
- 2Присвойте текст свойству Запрос.Текст или передайте в конструктор Новый Запрос(Текст)
- 3Установите все параметры через Запрос.УстановитьПараметр
- 4Выполните запрос и проверьте результат выборкой или Выгрузить()
- 5При ошибке выведите итоговый текст через Сообщить или в журнал для разбора
Подмена таблиц, полей и других идентификаторов
Главное ограничение языка запросов 1С: параметры (&Имя) передают только значения данных. Нельзя параметром подставить имя таблицы, поля, направление сортировки или вид виртуальной таблицы. Если структура запроса должна меняться — единственный путь это изменение строки текста до присвоения.
Типовые сценарии подстановки строкой: выбор регистра по имени из настроек отчёта, переключение поля сортировки, замена УПОРЯДОЧИТЬ ПО ... ВОЗР/УБЫВ, подстановка имени табличной части. Во всех этих случаях фрагмент вставляется в текст до выполнения.
Здесь кроется риск: если имя таблицы или поля приходит извне — из пользовательских настроек, файла обмена, параметра формы — прямая подстановка открывает возможность инъекции произвольного текста запроса. Безопасный приём — проверять подставляемое значение по белому списку допустимых вариантов или по метаданным:
Если Метаданные.РегистрыНакопления.Найти(ИмяРегистра) = Неопределено Тогда
ВызватьИсключение "Недопустимое имя регистра";
КонецЕсли;
Замена текста в уже готовом запросе
Иногда запрос уже написан, а поменять нужно небольшой фрагмент — например, добавить отбор или заменить таблицу. Для этого используют строковые функции: СтрЗаменить, СтрНайти, Лев, Сред. Типичный приём — маркеры-комментарии в тексте, по которым выполняется замена:
ТекстЗапроса = СтрЗаменить(ТекстЗапроса,
"//&УсловиеПоОрганизации",
"И Продажи.Организация = &Организация");
Такой подход работает, но хрупок: замена зависит от точного совпадения подстроки, включая регистр и пробелы. Рефакторинг исходного запроса может незаметно сломать место подстановки, и ошибка проявится только в конкретном сценарии выполнения.
Более надёжная альтернатива для сложных модификаций — объект СхемаЗапроса. Он разбирает текст запроса в объектную модель, где можно программно добавлять поля, отборы, соединения и порядок, а затем получить обратно корректный текст методом ПолучитьТекстЗапроса(). Это избавляет от ручного разбора строк и ошибок синтаксиса.
Сравнение вариантов
Подходит для простых динамических фрагментов: имя таблицы, направление сортировки. Ограничение — легко получить синтаксическую ошибку при сложной логике.
Подходит для точечной модификации готового текста. Ограничение — зависимость от точного совпадения подстроки, ломается при рефакторинге.
Подходит для серьёзной программной модификации запроса. Ограничение — не поддерживает абсолютно все конструкции языка запросов, громоздче для простых задач.
Запрос в макете и другие источники строки
Текст запроса не обязан жить в модуле. Распространённый приём — хранить его в макете типа «Текстовый документ» и читать через ПолучитьМакет(). Это удобно для больших запросов отчётов: текст не загромождает код, его проще редактировать и переносить между конфигурациями.
ТекстЗапроса = ПолучитьМакет("ЗапросОстатков").ПолучитьТекст();
Запрос = Новый Запрос(ТекстЗапроса);
У этого способа есть нюансы. Конструктор запроса из макета не вызывается — редактировать придётся вручную или временно копировать текст в модуль. Подстановки в таком тексте делаются теми же строковыми функциями после чтения. Также следите за кодировкой и невидимыми символами при копировании текста из внешних редакторов.
Ещё один источник строки — свойство Текст уже существующего запроса: его можно прочитать, изменить и присвоить другому объекту. Так строятся механизмы логирования запросов и универсальные обработки, клонирующие запросы с модификацией.
При отладке динамически собранного запроса выведите итоговый текст перед выполнением и вставьте его в консоль запросов. Там ошибка локализуется за секунды, тогда как по сообщению платформы в коде понять, какая именно подстановка сломала текст, бывает трудно.
Типичные ошибки и их диагностика
Большинство проблем с запросом как строкой сводится к нескольким повторяющимся причинам. Ошибка «Синтаксическая ошибка» при выполнении почти всегда означает, что при конкатенации потерян пробел или перенос строки между фрагментами: два слова склеились в одно. Лечится добавлением пробела или Символы.ПС на стыках фрагментов.
Ошибка вида «Поле не найдено» или «Таблица не найдена» указывает на неверно подставленный идентификатор: опечатку в имени из переменной, несуществующий реквизит или таблицу, недоступную в данной конфигурации. Проверяйте подставляемые имена по метаданным до сборки текста.
Отдельная группа — проблемы с параметрами: параметр упомянут в тексте, но не установлен, либо установлен до присвоения текста и «потерялся». Правило простое: сначала Запрос.Текст = ..., затем все УстановитьПараметр, затем Выполнить(). Проверить состав параметров помогает метод НайтиПараметры(), возвращающий те параметры, которые реально встречаются в текущем тексте.
Как проверить результат
Текст читается целиком, на стыках фрагментов есть пробелы или переносы
Слова склеены, фрагменты обрываются посреди конструкции
НайтиПараметры() возвращает все параметры из текста, каждый установлен
Параметр есть в тексте, но не установлен — ошибка при выполнении
Имена таблиц и полей существуют в метаданных
Имя пришло извне без проверки — риск ошибки или инъекции
Ответы на частые вопросы
Можно ли передать имя таблицы в запрос через параметр?
Нет. Параметры запроса передают только значения данных — числа, строки, даты, ссылки, массивы. Имя таблицы, поля или направление сортировки подставляется только изменением строки текста до присвоения свойству Текст, например через СтрШаблон.
Почему конструктор запроса не открывает мой текст?
Конструктор понимает только текст, заданный одним многострочным литералом в модуле. Если строка собирается конкатенацией с переменными, хранится в макете или формируется функцией, конструктор её не распарсит — редактируйте текст вручную или через консоль запросов.
Как экранировать кавычки внутри текста запроса в коде?
Внутри строкового литерала встроенного языка кавычка удваивается: вместо одной пишутся две подряд. Если кавычек много, надёжнее вынести строковое значение в параметр запроса — тогда экранирование вообще не нужно.
Чем СхемаЗапроса лучше ручной сборки строки?
СхемаЗапроса разбирает текст в объектную модель: пакеты, операторы, поля, отборы, соединения. Изменения вносятся методами объектов, а готовый корректный текст возвращается автоматически, что исключает синтаксические ошибки склейки. Минус — не все конструкции языка запросов поддерживаются и кода получается больше.
Как отладить динамически собранный запрос?
Перед выполнением выведите итоговый текст (например, через Сообщить или в журнал регистрации), скопируйте его в консоль запросов, установите там те же параметры и выполните. Консоль покажет точное место синтаксической ошибки и позволит быстро проверить корректность результата.
Опасно ли собирать запрос из строк, введённых пользователем?
Да, если речь об идентификаторах и фрагментах текста — это открывает возможность подмены запроса. Значения данных всегда передавайте параметрами, а подставляемые имена таблиц и полей проверяйте по белому списку или через Метаданные до сборки текста.
Что важно запомнить
Текст запроса в 1С — обычная строка: её задают литералом с вертикальной чертой, собирают конкатенацией или СтрШаблон и модифицируют через СтрЗаменить или СхемаЗапроса. Значения передавайте только параметрами, идентификаторы подставляйте в текст с проверкой по метаданным, а порядок всегда один: текст → параметры → выполнение.