В чем разница между оператором ССЫЛКА и функцией ЗНАЧЕНИЕ в параметрах запроса 1С

Программист 1С v8.3 (Управляемые формы) Бухгалтерский учет IT и автоматизация бизнеса
← На главную

При работе с виртуальными таблицами (особенно в регистрах бухгалтерии и накопления) начинающие разработчики часто сталкиваются с трудностями при попытке отфильтровать данные по конкретному виду документа или справочника. Основная путаница возникает вокруг конструкций ССЫЛКА и ЗНАЧЕНИЕ(). На первый взгляд они кажутся взаимозаменяемыми, но на уровне логики платформы и выполнения SQL-запроса они работают совершенно по-разному. В этой статье мы подробно разберем, почему попытка подставить тип метаданных в функцию ЗНАЧЕНИЕ() приводит к ошибке, как правильно проверять типы данных и какие "секретные" приемы существуют для обращения к пустым ссылкам.

Разбираем природу оператора ССЫЛКА

Рассмотрим ситуацию: нам необходимо выбрать движения по регистру бухгалтерии, но ограничить выборку только одним видом регистратора — например, "Реализация товаров и услуг". Для этого идеально подходит оператор ССЫЛКА. Проанализируем его работу. Оператор ССЫЛКА — это логическая операция, которая проверяет, принадлежит ли значение поля (например, СубконтоКт1 или Регистратор) к конкретному типу метаданных.

Важно понимать, что ССЫЛКА не сравнивает данные с конкретным объектом в базе. Она работает на уровне описания метаданных. Посмотрим на пример правильного использования в параметрах виртуальной таблицы:


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

В данном случае платформа 1С на уровне СУБД проанализирует поле типа (обычно это дополнительная колонка в таблице базы данных, хранящая идентификатор типа) и отсечет все записи, которые не являются реализациями. Это максимально производительный способ фильтрации по типу.

Особенности функции ЗНАЧЕНИЕ() и причины ошибок

Теперь выясним, почему конструкция ЗНАЧЕНИЕ(Документ.РеализацияТоваровУслуг) вызывает ошибку "Недопустимая длина" или "Несоответствие типов". Функция ЗНАЧЕНИЕ() — это литерал. Она предназначена для обращения к конкретным предопределенным данным, значениям перечислений или пустым ссылкам, которые известны в конфигураторе.

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

Правильное использование функции ЗНАЧЕНИЕ() предполагает указание конкретного пути:

  1. Для перечислений: ЗНАЧЕНИЕ(Перечисление.СтатусыЗаказов.Новый)
  2. Для пустых ссылок: ЗНАЧЕНИЕ(Документ.РеализацияТоваровУслуг.ПустаяСсылка)
  3. Для предопределенных элементов справочников: ЗНАЧЕНИЕ(Справочник.Валюты.Рубль)

Если ваша задача — найти записи, где документ просто не заполнен (пустой), то следует использовать сравнение с пустой ссылкой через ЗНАЧЕНИЕ(). Если же нужно найти все документы данного вида (и заполненные, и пустые), используется ССЫЛКА.

Хитрость с точкой: недокументированная особенность

В процессе обсуждения программисты обнаружили интересную особенность парсера запросов 1С. Если в функции ЗНАЧЕНИЕ() указать тип документа и поставить в конце точку, запрос отработает без ошибки:


// Это сработает и вернет Пустую Ссылку данного типа
СубконтоКт1 = ЗНАЧЕНИЕ(Документ.РеализацияТоваровУслуг.)

Проанализируем эту ситуацию. На самом деле такая запись интерпретируется платформой как краткий аналог обращения к ПустаяСсылка. Однако мы крайне не рекомендуем использовать этот метод в промышленной разработке. Во-первых, это делает код менее читаемым ("ректальное программирование", как выразились участники обсуждения), а во-вторых, поведение недокументированных функций может измениться в новых версиях платформы без предупреждения. Правильно писать полное имя: ЗНАЧЕНИЕ(Документ.Имя.ПустаяСсылка).

Когда использовать ВЫРАЗИТЬ() вместо ССЫЛКА

Иногда простого фильтра по типу через ССЫЛКА недостаточно. Рассмотрим ситуацию, когда нам нужно в одном запросе и отфильтровать данные по типу, и сразу получить реквизиты этого типа (например, склад из документа реализации, который находится в поле Регистратор составного типа).

В этом случае нам поможет оператор ВЫРАЗИТЬ(). Он не только проверяет тип, но и позволяет платформе оптимизировать SQL-запрос, явно указывая, к какой физической таблице нужно "джоиниться" (соединяться).


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

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

Подведем итоги: краткая шпаргалка

Для закрепления материала проанализируем три основных сценария работы с типами в запросах:

  1. Нужно отобрать все записи определенного типа (например, все Реализации): Используем Поле ССЫЛКА Документ.ИмяДокумента. Это быстро и правильно.
  2. Нужно сравнить поле с конкретным значением (например, со статусом "Отгружено" или пустой ссылкой): Используем Поле = ЗНАЧЕНИЕ(Перечисление.Статусы.Отгружено).
  3. Нужно получить реквизиты объекта из поля составного типа: Используем ВЫРАЗИТЬ(Поле КАК Документ.ИмяДокумента).Реквизит.

Помните, что фильтрация внутри параметров виртуальной таблицы (например, в третьем параметре ДвиженияССубконто) всегда предпочтительнее, чем фильтрация в секции ГДЕ. Это позволяет серверу 1С передать условия сразу на сторону СУБД и значительно сократить объем передаваемых данных.

← На главную