ВЫБРАТЬ, ИЗ, ГДЕ: первый запрос

Разбираем, зачем в 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 по ключевым словам, но только читает данные, работает со ссылками и умеет виртуальные таблицы регистров.
Проверьте себя
1. Как правильно указать источник данных для справочника Номенклатура в секции ИЗ запроса 1С?
AИЗ Справочники.Номенклатура
BИЗ Справочник.Номенклатура
CИЗ Номенклатура
DИЗ Справочники.Номенклатура.Выбрать()
2. Почему получить список дорогих товаров запросом обычно эффективнее, чем перебором справочника в цикле?
AЗапрос выполняется на клиенте, а цикл — на сервере
BВ цикле нельзя проверить условие на цену
CФильтрацию и выборку делает сервер СУБД и возвращает только нужные строки и поля
DЗапрос кэширует все товары в память один раз