Решение задач 1С:Предприятие 8 на примерах

Ссылка в запросе 1С: разыменование, ВЫРАЗИТЬ, пустая ссылка и GUID

ЗапросыОпубликовано

Ссылки — основа почти любого запроса в 1С, и от того, как вы с ними работаете, зависит и скорость запроса, и правильность результата. В статье — поле Ссылка, разыменование через точку и его цена, ВЫРАЗИТЬ для составных типов, проверка типа через ССЫЛКА и ТИПЗНАЧЕНИЯ, пустая ссылка и NULL, представление ссылки и получение ссылки по уникальному идентификатору.

Задача: правильно работать со ссылками в запросе

Ссылка в запросе 1С — это значение ссылочного типа: элемент справочника, документ, значение перечисления. Почти любой запрос оперирует ссылками: выбирает их из таблиц, сравнивает, фильтрует по типу, достаёт через них реквизиты связанных объектов. Здесь легко написать запрос, который работает правильно, но медленно, или быстрый, но возвращающий неверный результат на пустых и отсутствующих значениях.

Ниже — поле Ссылка, разыменование через точку и его цена, ВЫРАЗИТЬ для составных типов, проверка типа с помощью ТИПЗНАЧЕНИЯ и ССЫЛКА, пустая ссылка и ЕСТЬNULL, представления и получение ссылки по уникальному идентификатору. Имена объектов в примерах соответствуют типовым конфигурациям торговли и могут отличаться от ваших.

Поле Ссылка и разыменование через точку

У каждой таблицы ссылочного объекта (справочник, документ, план видов характеристик) есть предопределённое поле Ссылка. Оно же используется как ключ соединения. Реквизит ссылочного типа в запросе можно «разыменовать» — обратиться к полю связанного объекта через точку, причём цепочку можно продолжать.

ВЫБРАТЬ
    Реализация.Ссылка КАК Документ,
    Реализация.Контрагент КАК Контрагент,
    Реализация.Контрагент.ИНН КАК ИНН,
    Реализация.Контрагент.Родитель.Наименование КАК Группа
ИЗ
    Документ.РеализацияТоваровУслуг КАК Реализация
ГДЕ
    Реализация.Дата МЕЖДУ &Начало И &Конец

Удобство обманчиво. За каждой точкой платформа строит неявное левое соединение с таблицей связанного объекта. Одно-два разыменования на реквизитах с одним типом почти ничего не стоят. Когда точек много, а реквизит имеет составной тип, запрос получает соединения со всеми таблицами, входящими в тип, и становится тяжёлым. Для больших выборок, а также для условий и сортировки по связанным полям соединение лучше написать явно:

ВЫБРАТЬ
    Реализация.Ссылка КАК Документ,
    Контрагенты.ИНН КАК ИНН
ИЗ
    Документ.РеализацияТоваровУслуг КАК Реализация
        ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Контрагенты КАК Контрагенты
        ПО Реализация.Контрагент = Контрагенты.Ссылка

Явное соединение даёт оптимизатору больше возможностей и делает запрос читаемым. Параметры, выполнение и обход результата в целом описаны в статье Запросы в 1С.

ВЫРАЗИТЬ: приведение составного типа к одному

Реквизит или поле может иметь составной тип — например, Регистратор регистра принимает ссылки на десятки видов документов. Если разыменовать такое поле через точку, платформа соединит запрос со всеми документами из списка типов. Оператор ВЫРАЗИТЬ сообщает, что значение имеет один конкретный тип, и соединение остаётся одно:

ВЫБРАТЬ
    Товары.Регистратор КАК Регистратор,
    ВЫРАЗИТЬ(Товары.Регистратор КАК Документ.РеализацияТоваровУслуг).Контрагент КАК Контрагент
ИЗ
    РегистрНакопления.ТоварыНаСкладах КАК Товары
ГДЕ
    Товары.Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг

Условие ССЫЛКА в ГДЕ оставляет только записи, регистратор которых — реализация, а ВЫРАЗИТЬ приводит значение к этому типу. Для других записей конструкция вернёт NULL, но их уже отфильтровали. Для примитивных типов используются СТРОКА(100), ЧИСЛО(15, 2), ДАТА и БУЛЕВО.

Чтобы узнать тип значения без приведения, служит функция ТИПЗНАЧЕНИЯ, которая сравнивается с ТИП():

ВЫБРАТЬ
    Движения.Регистратор КАК Регистратор,
    ВЫБОР
        КОГДА Движения.Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг ТОГДА "Продажа"
        КОГДА Движения.Регистратор ССЫЛКА Документ.ПоступлениеТоваровУслуг ТОГДА "Покупка"
        ИНАЧЕ "Прочее"
    КОНЕЦ КАК ВидОперации
ИЗ
    РегистрНакопления.ТоварыНаСкладах КАК Движения
ГДЕ
    ТИПЗНАЧЕНИЯ(Движения.Регистратор) В (ТИП(Документ.РеализацияТоваровУслуг), ТИП(Документ.ПоступлениеТоваровУслуг))

Пустая ссылка в запросе

Пустая ссылка — значение ссылочного типа, которое не указывает ни на какой объект. Реквизит, который не заполнен, содержит именно её. Для сравнения используют функцию ЗНАЧЕНИЕ() либо параметр:

ГДЕ
    Реализация.Договор = ЗНАЧЕНИЕ(Справочник.ДоговорыКонтрагентов.ПустаяСсылка)

// или параметром
Запрос.УстановитьПараметр("Договор", Справочники.ДоговорыКонтрагентов.ПустаяСсылка());

Обратите внимание на скобки: в запросе это ЗНАЧЕНИЕ(Справочник.X.ПустаяСсылка) без скобок, а в коде — метод менеджера ПустаяСсылка().

Не путайте пустую ссылку и NULL. Пустая ссылка существует в данных. NULL появляется, когда у левого соединения нет подходящей строки справа, и сравнивать его через равенство бесполезно: результат сравнения с NULL не истинен. Для такой проверки служат ЕСТЬ NULL и функция ЕСТЬNULL:

ВЫБРАТЬ
    Реализация.Ссылка КАК Документ,
    ЕСТЬNULL(Договоры.Ссылка, ЗНАЧЕНИЕ(Справочник.ДоговорыКонтрагентов.ПустаяСсылка)) КАК Договор
ИЗ
    Документ.РеализацияТоваровУслуг КАК Реализация
        ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ДоговорыКонтрагентов КАК Договоры
        ПО Реализация.Договор = Договоры.Ссылка
ГДЕ
    Договоры.Ссылка ЕСТЬ NULL

Этот запрос найдёт документы, у которых договор не заполнен или указывает на несуществующий элемент. Если нужно только «не заполнено», достаточно сравнения с пустой ссылкой; ЕСТЬ NULL понадобится именно тогда, когда в игре левое соединение. Подробности о соединениях выходят за рамки статьи, но следует запомнить, что любое условие по правой таблице в ГДЕ, кроме проверки ЕСТЬ NULL, отбрасывает строки без пары, и левое соединение превращается во внутреннее — это известная ловушка.

Представление ссылки

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

ВЫБРАТЬ
    Реализация.Ссылка КАК Ссылка,
    ПРЕДСТАВЛЕНИЕССЫЛКИ(Реализация.Ссылка) КАК ДокументТекст,
    ПРЕДСТАВЛЕНИЕ(Реализация.Контрагент) КАК КонтрагентТекст
ИЗ
    Документ.РеализацияТоваровУслуг КАК Реализация

ПРЕДСТАВЛЕНИЕССЫЛКИ() возвращает строку, как её показывает интерфейс (например, «Реализация товаров и услуг 000000012 от 12.05.2026»), а ПРЕДСТАВЛЕНИЕ() применяется к полю любого типа и подходит для перечислений и составных значений. Результат предназначен для вывода, а не для условий и связей.

Уникальный идентификатор в запросе

Внутренний идентификатор (GUID) ссылки нужен при обмене данными с внешними системами, для сопоставления объектов и при диагностике «битых» ссылок. В платформе версии 8.3.22 и новее в языке запросов появилась функция УНИКАЛЬНЫЙИДЕНТИФИКАТОР(), которая возвращает идентификатор переданной ссылки:

ВЫБРАТЬ
    Номенклатура.Ссылка КАК Ссылка,
    УНИКАЛЬНЫЙИДЕНТИФИКАТОР(Номенклатура.Ссылка) КАК УИД
ИЗ
    Справочник.Номенклатура КАК Номенклатура

В более старых платформах идентификатор получают уже в коде при обходе выборки: Выборка.Ссылка.УникальныйИдентификатор() или XMLСтрока(Выборка.Ссылка), что даёт строку-идентификатор.

Обратная задача — найти объект по известному идентификатору. Менеджер справочника умеет создавать ссылку по GUID, и эту ссылку передают в запрос параметром:

Идентификатор = Новый УникальныйИдентификатор("f5e9a1c0-3b7d-4c5a-9a6e-2d1c8b7f4e30");
Ссылка = Справочники.Номенклатура.ПолучитьСсылку(Идентификатор);

Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
|    Номенклатура.Наименование КАК Наименование
|ИЗ
|    Справочник.Номенклатура КАК Номенклатура
|ГДЕ
|    Номенклатура.Ссылка = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", Ссылка);
Результат = Запрос.Выполнить();

Важная деталь: ПолучитьСсылку() создаёт ссылку, не проверяя, есть ли такой элемент в базе. Если объекта нет, запрос просто вернёт пустой результат — по нему и проверяйте существование. Если идентификатор приходит строкой из внешней системы, для типизированной ссылки можно воспользоваться XMLЗначение(Тип("СправочникСсылка.Номенклатура"), СтрокаXML).

Список ссылок в условии

Часто в запрос нужно передать набор ссылок: выбранные пользователем номенклатурные позиции, документы для проведения. Для этого в параметр кладут массив, а в условии используют оператор В:

Запрос.Текст =
"ВЫБРАТЬ
|    Номенклатура.Ссылка КАК Ссылка,
|    Номенклатура.Артикул КАК Артикул
|ИЗ
|    Справочник.Номенклатура КАК Номенклатура
|ГДЕ
|    Номенклатура.Ссылка В(&МассивНоменклатуры)";
Запрос.УстановитьПараметр("МассивНоменклатуры", МассивНоменклатуры);

Если ссылок тысячи, массив лучше передать через временную таблицу и соединить её с основной выборкой: так оптимизатору проще подобрать план, а размер текста запроса не растёт. Элементы массива должны быть именно ссылками, а не строками или структурами — иначе условие вернёт пустой результат.

Что выбрать: точка, соединение или ВЫРАЗИТЬ

СпособКогда подходитОсобенность
Разыменование через точкуНебольшие выборки, реквизиты с одним типомКоротко пишется, но неявное соединение; для составных типов может быть тяжёлым
Явное ЛЕВОЕ СОЕДИНЕНИЕБольшие выборки, условия и сортировка по связанным полямЧитаемо и предсказуемо по плану запроса
ВЫРАЗИТЬ ... КАК ТипРегистраторы и другие составные поляСнимает лишние соединения; сочетается с ССЫЛКА в условии

Типичные ошибки

  • Длинные цепочки точек по реквизитам составного типа: запрос соединяет десятки таблиц.
  • Сравнение с NULL знаком равенства (Поле = NULL) вместо ЕСТЬ NULL.
  • Ожидание, что левое соединение вернёт пустую ссылку: на самом деле возвращается NULL, пока его не превратили через ЕСТЬNULL.
  • Условие по правой таблице левого соединения в ГДЕ (кроме ЕСТЬ NULL) — запрос ведёт себя как внутреннее соединение; такие условия переносят в ПО.
  • Передача в параметр запроса строки вместо ссылки: сравнение не срабатывает, пока строку не преобразуют в ссылку.
  • Использование ПолучитьСсылку() как проверки существования объекта: метод не обращается к базе.
  • Использование функции УНИКАЛЬНЫЙИДЕНТИФИКАТОР() на платформах старше 8.3.22: запрос завершится ошибкой — получайте идентификатор в коде.

Актуальность для новых версий

Базовые конструкции запроса — поле Ссылка, ВЫРАЗИТЬ, ССЫЛКА, ТИПЗНАЧЕНИЯ, ПРЕДСТАВЛЕНИЕ — одинаково работают во всех релизах 8.3. Функция УНИКАЛЬНЫЙИДЕНТИФИКАТОР() в языке запросов доступна начиная с платформы 8.3.22; в более ранних версиях идентификатор получают в коде методом УникальныйИдентификатор() ссылки. Названия объектов в примерах соответствуют типовым конфигурациям и в вашей базе могут отличаться.

Частые вопросы

Чем разыменование через точку отличается от соединения?

Точка создаёт неявное левое соединение, и для составных типов оно строится со всеми таблицами типа. Явное соединение даёт больше контроля и обычно работает быстрее на больших выборках.

Как проверить в запросе, что ссылка пустая?

Сравните поле с ЗНАЧЕНИЕ(Справочник.Имя.ПустаяСсылка) или с параметром, куда передано Справочники.Имя.ПустаяСсылка(). Для проверки отсутствия строки в левом соединении используйте ЕСТЬ NULL.

Как выбрать записи регистра только по документам определённого вида?

В условии укажите Регистратор ССЫЛКА Документ.ИмяДокумента. Если нужны реквизиты этого документа, приведите регистратор через ВЫРАЗИТЬ(Регистратор КАК Документ.ИмяДокумента).

Как найти объект по GUID?

Создайте ссылку методом Менеджер.ПолучитьСсылку(Новый УникальныйИдентификатор("...")) и передайте её в запрос параметром. Метод не проверяет существование, поэтому наличие объекта определяют по результату запроса.

Строка в запросе 1С: ПОДОБНО, ПОДСТРОКА и строки неограниченной длины

Запросы

Как работать со строками в языке запросов 1С: искать по шаблону через ПОДОБНО, вырезать часть строки, сравнивать поля неограниченной длины и склеивать текст без ошибок с NULL.

Дата в запросе 1С: ДАТАВРЕМЯ, период, МЕЖДУ, пустая и текущая дата

Запросы

Все приёмы работы с датами в языке запросов 1С: литералы и параметры, отбор за период, дата без времени, извлечение года и месяца, разность и сдвиг дат, пустая и текущая дата.

Запросы в 1С: как написать запрос, передать параметры и обработать результат

Запросы

Пошаговый разбор работы с запросами в 1С: текст и параметры, обход результата и выгрузка в таблицу значений, пакетные запросы с временными таблицами и отладка в консоли запросов.

Запрос 1С, который генерирует даты по дням за период

Запросы

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