При разработке запросов в системе «1С:Предприятие» программисты регулярно сталкиваются с необходимостью жестко типизировать колонку выборки. Это нужно для создания пустых типизированных полей, которые в дальнейшем будут заполняться данными, для корректного построения схем компоновки данных (СКД), работы динамических списков или последующей выгрузки результата в Таблицу Значений. Если со строками и числами все достаточно очевидно (используются конструкции вида "" КАК СтроковоеПоле или 0 КАК ЧисловоеПоле), то со ссылочными типами данных (справочники, документы, процессы) у начинающих разработчиков часто возникают трудности.
В этой статье мы подробно разберем, как установить тип ссылки в запросе 1С, рассмотрим альтернативные методы типизации, а также проанализируем неочевидные нюансы работы платформы при выгрузке таких запросов в коллекции значений.
Самый простой, быстрый и наиболее распространенный способ установить конкретный ссылочный тип для колонки — это использование встроенной функции запроса ЗНАЧЕНИЕ(). Данная функция позволяет получить пустую ссылку нужного справочника или документа непосредственно в теле запроса.
Давайте посмотрим на практический пример. Предположим, нам нужно получить пустую колонку с типом ссылки на справочник «Номенклатура». Мы можем написать следующий запрос:
ВЫБРАТЬ
"Пример текста" КАК ТекстовоеПоле,
0 КАК ЧисловоеПоле,
ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка) КАК Номенклатура
Рассмотрим подробнее синтаксис функции ЗНАЧЕНИЕ(). В качестве параметра она принимает строго определенный путь к объекту метаданных. Конструкция всегда строится по схеме:
ЗНАЧЕНИЕ(<ТипОбъекта>.<ИмяОбъекта>.ПустаяСсылка)
Этот способ идеален, когда тип данных известен заранее на этапе разработки и жестко зафиксирован в конфигурации. Кроме пустых ссылок, функция ЗНАЧЕНИЕ() позволяет обращаться к предопределенным элементам справочников или системным перечислениям, например: ЗНАЧЕНИЕ(Перечисление.СтатусыДокументов.Проведен).
Существует еще один изящный способ приведения типа, о котором разработчики часто забывают — использование оператора ВЫРАЗИТЬ() совместно с системным значением NULL.
Давайте разберем, как выглядит этот синтаксис:
ВЫБРАТЬ
ВЫРАЗИТЬ(NULL КАК Справочник.Номенклатура) КАК Номенклатура
Выясним причину, почему этот способ так популярен среди профессиональных разработчиков и в чем его принципиальное отличие от первого варианта:
ЗНАЧЕНИЕ(...), которая физически возвращает пустую ссылку (уникальный идентификатор, состоящий из нулей), конструкция ВЫРАЗИТЬ(NULL...) возвращает значение NULL.NULL, сама колонка запроса на уровне метаданных жестко типизируется выбранным ссылочным типом.ВЫРАЗИТЬ(), мы можем затем программно заполнять ее значениями на сервере (например, в событии ПриПолученииДанныхНаСервере), при этом платформа будет четко знать тип данных этой колонки.Что делать, если имя справочника или документа заранее неизвестно? Например, вы пишете универсальный отчет или обработку, где тип данных выбирается пользователем на форме. В этом случае жестко прописать имя объекта в тексте запроса не получится.
Для решения этой задачи мы можем передать пустую ссылку нужного типа через параметры запроса. Давайте посмотрим, как это реализовать в коде:
// 1. Формируем текст запроса с параметром
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| &ПараметрПустаяСсылка КАК СсылкаНаОбъект";
// 2. Определяем имя нужного справочника динамически
ИмяСправочника = "Контрагенты"; // Может приходить из настроек
// 3. Устанавливаем параметр, получая пустую ссылку через метаданные
ПустаяСсылка = Справочники[ИмяСправочника].ПустаяСсылка();
Запрос.УстановитьПараметр("ПараметрПустаяСсылка", ПустаяСсылка);
РезультатЗапроса = Запрос.Выполнить();
Этот метод обеспечивает максимальную гибкость вашего кода, позволяя динамически типизировать колонки запроса под любые задачи автоматизации бизнеса.
При использовании конструкции ОБЪЕДИНИТЬ ВСЕ платформа 1С определяет итоговый тип колонки на основе типов данных из всех объединяемых частей запроса. Чтобы избежать появления нежелательных составных типов (которые могут сильно замедлить работу СУБД), необходимо придерживаться важного правила.
Правило: Всегда явно типизируйте пустые колонки в самой первой ветке объединения запросов.
Проанализируем пример некорректного и корректного запроса:
// НЕПРАВИЛЬНО: Во второй ветке у нас Номенклатура, а в первой - NULL без указания типа.
// Это приведет к неоптимальной типизации.
ВЫБРАТЬ
NULL КАК Товар
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
Реализация.Номенклатура
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализация
// ПРАВИЛЬНО: Явно типизируем первую ветку
ВЫБРАТЬ
ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка) КАК Товар
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
Реализация.Номенклатура
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализация
При работе с результатом запроса программисты часто совершают выгрузку данных в Таблицу Значений с помощью метода Выгрузить(). Здесь кроется важная техническая деталь поведения платформы 1С:
Null. То есть тип колонки в полученной Таблице Значений становится составным (например, СправочникСсылка.Номенклатура и Null).ТаблицаДанных.Добавить(), то значение в типизированной колонке по умолчанию инициализируется не пустой ссылкой номенклатуры, а значением Неопределено!Для обхода этой особенности после выгрузки результата запроса в Таблицу Значений рекомендуется программно очищать колонки или явно приводить их типы, если предполагается дальнейшее добавление строк вручную.
Если вам требуется не просто создать пустую колонку, а проверить тип данных существующего поля (например, когда реквизит «ДокументОснование» имеет составной тип), используйте оператор ССЫЛКА. Это гораздо эффективнее с точки зрения производительности СУБД, чем использование функций ТИПЗНАЧЕНИЯ().
Пример использования оператора ССЫЛКА в условиях запроса:
ВЫБРАТЬ
Заказы.Ссылка КАК Заказ,
Заказы.ДокументОснование КАК Основание
ИЗ
Документ.ЗаказПокупателя КАК Заказы
ГДЕ
Заказы.ДокументОснование ССЫЛКА Документ.РеализацияТоваровУслуг
Подводя итог, можно сказать, что выбор метода типизации зависит от контекста вашей задачи. Для простых статических запросов идеально подходит функция ЗНАЧЕНИЕ(). Если вы проектируете динамический список или сложный интерфейсный отчет, обратите внимание на ВЫРАЗИТЬ(NULL КАК...). Для универсальных алгоритмов лучшим выбором станет передача пустой ссылки через параметры запроса.