ВЫБРАТЬ, ИЗ, ГДЕ: первый запрос
Разбираем, зачем в 1С вообще нужны запросы и как выглядит самый первый из них — ВЫБРАТЬ...ИЗ...ГДЕ.
Запрос 1С — это текст на специальном языке запросов, который просит у платформы нужный срез данных из базы: какие поля взять, из какой таблицы и по какому условию отобрать строки.
Представьте, что вам нужно вывести список товаров дороже 1000 рублей. Первое, что приходит в голову новичку, — пройтись по всей номенклатуре в цикле и на каждом элементе проверить цену. Это работает на десяти позициях и превращается в катастрофу на десяти тысячах. Запрос решает ту же задачу одной формулировкой, и — это ключевая мысль — фактическую выборку и фильтрацию выполняет не ваш код, а сервер базы данных, который умеет делать это на порядки быстрее.
Зачем запрос вместо цикла
Сравним два подхода к одной и той же задаче. Вот наивный перебор всей номенклатуры «в лоб»:
Выборка = Справочники.Номенклатура.Выбрать();
Пока Выборка.Следующий() Цикл
Если Выборка.Цена > 1000 Тогда
Сообщить(Выборка.Наименование);
КонецЕсли;
КонецЦикла;Здесь платформа поднимает в память каждую строку справочника, гоняет её через клиентский код и только потом отсеивает лишнее. А теперь то же самое запросом:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Наименование,
| Номенклатура.Цена
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Цена > 1000";
Результат = Запрос.Выполнить();Разница не только в красоте. Во втором случае сервер вернёт уже только подходящие строки и только два запрошенных поля. Меньше данных по сети, меньше памяти, меньше работы. Запрос — это декларативность: вы описываете что хотите получить, а как это добыть эффективно, решает платформа.
Обратите внимание на символ вертикальной черты | в начале строк. Это не часть языка запросов, а способ 1С многострочно склеивать текст запроса в коде: всё, что после |, — продолжение той же строковой константы. Сам запрос эту черту не видит.
Из чего состоит ВЫБРАТЬ...ИЗ...ГДЕ
Минимальный запрос держится на трёх ключевых словах, и порядок у них строгий.
ВЫБРАТЬ — какие поля
После ВЫБРАТЬ перечисляют поля через запятую. Можно взять реквизиты объекта, а можно и сам объект целиком (его ссылку):
ВЫБРАТЬ
Номенклатура.Ссылка,
Номенклатура.Наименование,
Номенклатура.АртикулЕсли нужны все поля, ставят звёздочку: ВЫБРАТЬ *. В учебных примерах это удобно, но в рабочем коде так почти не делают — лишние поля тормозят запрос. Перечисляйте только то, что реально используете.
ИЗ — из какой таблицы
После ИЗ указывают источник данных. Здесь важнейший момент для новичка: имя таблицы пишется не так, как объект в коде. В коде вы обращаетесь к Справочники.Номенклатура (во множественном числе, через менеджер), а в запросе таблица называется Справочник.Номенклатура — в единственном числе. Тому же правилу подчиняются документы (Документ.РеализацияТоваровУслуг), перечисления, регистры.
После имени таблицы почти всегда ставят псевдоним через КАК:
ИЗ
Справочник.Номенклатура КАК НоменклатураПсевдоним — это короткое имя, по которому мы дальше в запросе обращаемся к полям таблицы. Здесь он совпал с именем таблицы, но мог быть любым: КАК Т, КАК Ном. Псевдонимы становятся обязательными, как только таблиц в запросе несколько.
ГДЕ — по какому условию
Секция ГДЕ необязательна, но именно она отсеивает ненужные строки. Условия соединяют логическими операторами И, ИЛИ, НЕ — словами, как и во встроенном языке 1С:
ГДЕ
Номенклатура.Цена >= 1000
И Номенклатура.ПометкаУдаления = ЛОЖЬ
И НЕ Номенклатура.ЭтоГруппаЗдесь мы берём только непомеченные на удаление элементы (не группы) с ценой от 1000. Операторы сравнения обычные: =, >, <, >=, <=, а «не равно» записывается как <>.
Как это работает
Полезно понимать, что происходит «под капотом», когда вы вызываете Запрос.Выполнить(). Платформа берёт ваш текст на языке запросов 1С и транслирует его в SQL того сервера базы данных, который стоит под системой (чаще всего это Microsoft SQL Server или PostgreSQL). То есть 1С — это переводчик: вы пишете на понятном русскоязычном диалекте, а СУБД получает привычный ей SQL.
Именно поэтому запрос быстрый: тяжёлую работу — чтение с диска, фильтрацию, использование индексов — делает промышленная СУБД, а не интерпретатор встроенного языка. Ваш код лишь отправляет текст и забирает готовый результат.
Ещё один нюанс: платформа при переводе автоматически учитывает права доступа текущего пользователя (RLS, ограничения на уровне записей). Если пользователю нельзя видеть какие-то товары, они просто не попадут в результат — вам об этом заботиться не нужно.
Похоже и не похоже на SQL
Если вы знаете SQL, язык запросов 1С покажется знакомым — и это не случайно. Общего действительно много:
| SQL | Язык запросов 1С |
SELECT | ВЫБРАТЬ |
FROM | ИЗ |
WHERE | ГДЕ |
AS | КАК |
AND / OR / NOT | И / ИЛИ / НЕ |
А вот принципиальные отличия, из-за которых язык запросов 1С — это не SQL:
- Только чтение. В языке запросов 1С нет
INSERT,UPDATE,DELETE. Запрос умеет лишь читать данные. Менять их можно только через объектную модель (.Записать()) — так платформа гарантирует целостность и отработку бизнес-логики. - Работа со ссылками, а не с ключами. В 1С вы оперируете ссылками на объекты (
Номенклатура.Ссылка), а не числовыми внешними ключами. Обращаться к реквизитам связанного объекта можно через точку:Товары.Номенклатура.ЕдиницаИзмерения.Наименование— платформа сама подставит нужные соединения. - Виртуальные таблицы. У 1С есть таблицы, которых физически в базе нет:
РегистрНакопления.Товары.Остатки(...),РегистрСведений.Цены.СрезПоследних(...). Их платформа рассчитывает на лету — в чистом SQL такого нет. - Русскоязычный синтаксис. Ключевые слова по-русски, что для русскоязычной команды снижает порог входа.
Частые ошибки
Пишут имя таблицы во множественном числе. ИЗ Справочники.Номенклатура — ошибка. В запросе только Справочник.Номенклатура, в единственном числе. Множественное число (Справочники) — это менеджер объектов во встроенном языке, а не имя таблицы.
Забывают псевдоним и обращаются к полю по имени таблицы. Если написали Справочник.Номенклатура КАК Ном, то дальше поле — это Ном.Цена, а не Номенклатура.Цена. Псевдоним, если он задан, становится единственным способом адресовать таблицу.
Пробуют менять данные запросом. Попытка написать UPDATE или ВЫБРАТЬ с изменением ничего не изменит: запрос принципиально только читает. Данные меняют объектом.
Тащат лишние поля через звёздочку. ВЫБРАТЬ * на большой таблице поднимает все реквизиты, включая ненужные, и грузит сеть. В рабочем коде перечисляйте поля явно.
Путают язык запросов и встроенный язык. В запросе нельзя вызвать произвольную функцию 1С вроде СокрЛП() или обратиться к переменной модуля. Запрос живёт в своей «песочнице»: у него свой набор операторов и функций, а данные снаружи передаются только через параметры (об этом — в следующем уроке).
Итоги
- Запрос получает данные декларативно: вы описываете нужный срез, а СУБД добывает его быстро — это всегда лучше перебора справочника в цикле.
- Каркас любого запроса —
ВЫБРАТЬ(поля) →ИЗ(таблица) →ГДЕ(условие), в строго этом порядке. - Имя таблицы в запросе — в единственном числе:
Справочник.Номенклатура,Документ.РеализацияТоваровУслуг. - Псевдоним через
КАК— короткое имя таблицы; при нескольких таблицах он обязателен. - Язык запросов 1С похож на SQL по ключевым словам, но только читает данные, работает со ссылками и умеет виртуальные таблицы регистров.