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

Особенность заключается в том, что типы данных здесь делятся на примитивные (число, строка, дата) и ссылочные (справочники, документы, планы видов характеристик). При этом в запросах ссылочные типы представляются как строки, но ведут себя иначе при операциях. Например, поле Ссылка в таблице документов формально имеет тип "Строка", но фактически содержит идентификатор объекта метаданных. Это создаёт путаницу при написании универсальных запросов.

1. Функция ТИП(): базовый метод определения типа

Функция ТИП(<Выражение>) возвращает строку с именем типа значения. Это самый простой способ узнать, с чем вы работаете. Например:

ВЫБРАТЬ

ТИП(100) КАК ТипЧисла,

ТИП("Привет") КАК ТипСтроки,

ТИП(ДАТАВРЕМЯ(2023, 1, 1)) КАК ТипДатаВремя

Результат выполнения этого запроса:

ТипЧислаТипСтрокиТипДатаВремя
ЧислоСтрокаДата

Однако у ТИП() есть ограничения:

  • 🔹 Не различает ссылочные типы (например, для справочника и документа вернёт просто "Строка").
  • 🔹 Не работает с NULL — при передаче неопределённого значения вернёт ошибку.
  • 🔹 Не учитывает контекст метаданных (например, не отличит "Документ.РеализацияТоваровУслуг" от "Документ.ПоступлениеТоваров").
⚠️ Внимание: В платформе 1С:Предприятие 8.3.20+ функция ТИП() может возвращать расширенные имена типов для некоторых ссылочных объектов (например, "СправочникСсылка.Номенклатура"). Но это поведение не документировано и может измениться в будущих версиях.

2. ТИПЗНАЧЕНИЯ(): отличие от ТИП() и когда использовать

Функция ТИПЗНАЧЕНИЯ(<Выражение>) похожа на ТИП(), но возвращает не строку, а значение перечисления ТипЗначения. Это удобно для программной обработки типов в коде после выполнения запроса. Пример:

ВЫБРАТЬ

ТИПЗНАЧЕНИЯ(100) КАК ТипЧисла,

ТИПЗНАЧЕНИЯ("Привет") КАК ТипСтроки

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

КритерийТИП()ТИПЗНАЧЕНИЯ()
Возвращаемый форматСтрокаЗначение перечисления
Работа с NULLОшибкаОшибка
Использование в условииТребует сравнения строкМожно сравнивать напрямую
ПроизводительностьВышеНиже (из-за приведения к перечислению)

Где уместно использовать ТИПЗНАЧЕНИЯ():

  • 📌 Когда результат запроса обрабатывается в модуле, и нужны именно значения перечисления для логики.
  • 📌 При динамическом формировании условий в запросе на основе типов (например, в отчётах с гибкими фильтрами).
  • 📌 В сложных вычисляемых полях, где требуется универсальная проверка типа.
📊 Какой функцией для определения типа вы пользуетесь чаще?
ТИП()
ТИПЗНАЧЕНИЯ()
ВЫРАЗИТЬ
Другие методы

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

Функция ВЫРАЗИТЬ(<Выражение> КАК <Тип>) не только преобразует значения, но и может использоваться для проверки типа. Если приведение возможно — значит, исходный тип совместим с целевым. Например:

ВЫБРАТЬ

ВЫРАЗИТЬ("123" КАК ЧИСЛО) КАК ЧислоИзСтроки,

ВЫБРАЗИТЬ(ДАТАВРЕМЯ(2023, 1, 1) КАК СТРОКА) КАК СтрокаИзДаты

Если приведение невозможно (например, ВЫРАЗИТЬ("Привет" КАК ЧИСЛО)), запрос вернёт ошибку. Это позволяет использовать ВЫРАЗИТЬ для валидации типов:

ВЫБРАТЬ

ЕСТЬNULL(ВЫРАЗИТЬ(ПолеТаблицы КАК ЧИСЛО), 0) КАК ЧисловоеЗначение

В этом примере если ПолеТаблицы не является числом, вместо ошибки вернётся 0.

⚠️ Внимание: Функция ВЫРАЗИТЬ может вести себя неочевидным образом со ссылочными типами. Например, приведение справочника к строке вернёт его УИД, а не наименование. Для получения наименования используйте Представление().

Таблица совместимости приведений типов:

Исходный типЧислоСтрокаДатаБулево
Число
Строка⚠️ (если формат числа)⚠️ (если формат даты)⚠️ ("Истина"/"Ложь")
Дата
Булево✅ ("Истина"/"Ложь")
💡

Для проверки возможности приведения без ошибок используйте конструкцию ВЫБРАТЬ ЕСТЬNULL(ВЫРАЗИТЬ(Поле КАК ЧИСЛО), ЛОЖЬ) КАК ЯвляетсяЧислом. Это вернёт Истина только если приведение возможно.

4. Работа со ссылочными типами: ССЫЛКА и МЕТАДАННЫЕ()

Ссылочные типы (справочники, документы, планы видов характеристик) в запросах представляются как строки, но имеют специальные методы для работы. Чтобы определить, является ли поле ссылочным, используйте:

ВЫБРАТЬ

ЕСТЬNULL(МЕТАДАННЫЕ(Объект.Ссылка).Имя, "") КАК ТипОбъекта

ИЗ

Документ.РеализацияТоваровУслуг КАК Объект

Функция МЕТАДАННЫЕ() возвращает объект метаданных для ссылочного поля. Его свойства:

  • 📖 .Имя — имя типа (например, "Справочник.Номенклатура").
  • 📖 .Синоним — синоним типа.
  • 📖 .ПолноеИмя — полное имя с учётом владельцев (например, "Справочник.Номенклатура.Товары").

Пример проверки типа документа:

ВЫБРАТЬ

ВЫБОР

КОГДА МЕТАДАННЫЕ(Док.Ссылка).Имя = "Документ.РеализацияТоваровУслуг"

ТОГДА "Реализация"

КОГДА МЕТАДАННЫЕ(Док.Ссылка).Имя = "Документ.ПоступлениеТоваров"

ТОГДА "Поступление"

ИНАЧЕ "Другой документ"

КАК ТипДокумента

ИЗ

Документ КАК Док

⚠️ Внимание: Функция МЕТАДАННЫЕ() работает только в контексте запроса к базе данных. В вычисляемых полях на клиенте она недоступна. Для клиентской логики используйте методы глобального контекста, например Метаданные.Справочники.Номенклатура.

5. Проверка типа через ЕСТЬ NULL и конструкцию ВЫБОР КОГДА

Иногда определить тип можно косвенно, анализируя поведение значения при операциях. Например, даты и числа ведут себя по-разному при сложении:

ВЫБРАТЬ

ВЫБОР

КОГДА ТИП(Значение) = "Дата" ТОГДА "Дата"

КОГДА ТИП(Значение) = "Число" ТОГДА "Число"

КОГДА ЕСТЬNULL(ВЫРАЗИТЬ(Значение КАК ЧИСЛО), 0) <> 0 ТОГДА "Строка-число"

ИНАЧЕ "Другой тип"

КАК ТипЗначения

ИЗ

(ВЫБРАТЬ 100 КАК Значение)

ОБЪЕДИНИТЬ ВСЕ

(ВЫБРАТЬ "123" КАК Значение)

ОБЪЕДИНИТЬ ВСЕ

(ВЫБРАТЬ ДАТАВРЕМЯ(2023, 1, 1) КАК Значение)

Этот подход полезен, когда:

  • 🔍 Нужно отличить строки, которые можно преобразовать в числа, от обычных строк.
  • 🔍 Требуется универсальная обработка полей с неизвестной структурой (например, в динамических отчётах).
  • 🔍 Работаете с унаследованными базами, где типы полей не документированы.

Единственный способ надёжно отличить ссылочный тип от строки — использовать МЕТАДАННЫЕ(). Все остальные методы (включая ТИП()) вернут для ссылки строку "Строка".

1. Использовать ТИП() для примитивных типов

2. Применить МЕТАДАННЫЕ() для ссылочных объектов

3. Проверить возможность приведения через ВЫРАЗИТЬ

4. Учесть NULL-значения с помощью ЕСТЬNULL

5. Для динамических отчётов заложить обработку всех вариантов типов-->

6. Ошибки и ловушки при работе с типами в запросах

Даже опытные разработчики сталкиваются с неочевидными проблемами при определении типов. Рассмотрим типичные ошибки:

  1. 🚫 Путаница со строками и ссылками: Как упоминалось ранее, ТИП() вернёт для ссылки "Строка". Это приводит к ошибкам при фильтрации:
    // Неверно: отберёт все строки, включая ссылки
    

    ГДЕ ТИП(Поле) = "Строка"

    // Правильно: явная проверка на ссылочный тип

    ГДЕ НЕ МЕТАДАННЫЕ(Поле) ЕСТЬ NULL

  2. 🚫 NULL в вычисляемых полях: Функции ТИП() и ТИПЗНАЧЕНИЯ() не работают с NULL. Используйте ЕСТЬNULL:
    ВЫБРАТЬ
    

    ЕСТЬNULL(ТИП(ЕСТЬNULL(Поле, 0)), "NULL") КАК ТипПоля

  3. 🚫 Неявное приведение типов: иногда автоматически преобразует типы, что маскирует ошибки. Например, сравнение строки "100" с числом 100 вернёт Истина, но только если строка может быть интерпретирована как число. Это поведение зависит от настроек совместимости базы.

Для отладки сложных запросов используйте конструкцию ВЫВЕСТИ (в отладочном режиме) или временные таблицы:

ВЫБРАТЬ

Поле КАК Значение,

ТИП(Поле) КАК Тип,

ЕСТЬNULL(МЕТАДАННЫЕ(Поле).Имя, "") КАК Метаданные

В

ВременнаяТаблица

ИЗ

ВашаТаблица

;

Почему ТИП() возвращает "Строка" для ссылок?

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

7. Практические примеры: от простого к сложному

Разберём реальные кейсы, где определение типа критично.

Пример 1: Фильтрация документов по типу

Задача: выбрать все документы типа "РеализацияТоваровУслуг" из объединённой выборки.

ВЫБРАТЬ

Док.Ссылка КАК Документ

ИЗ

Документ КАК Док

ГДЕ

МЕТАДАННЫЕ(Док.Ссылка).Имя = "Документ.РеализацияТоваровУслуг"

Пример 2: Универсальный отчёт с динамическими полями

Задача: создать отчёт, который автоматически определяет типы полей и форматирует их.

ВЫБРАТЬ

ВЫБОР

КОГДА ТИП(Значение) = "Дата" ТОГДА ФОРМАТ(Значение, "ДФ=dd.MM.yyyy")

КОГДА ТИП(Значение) = "Число" ТОГДА ФОРМАТ(Значение, "ЧГ=0")

КОГДА МЕТАДАННЫЕ(Значение) ЕСТЬ NULL ТОГДА ПРЕДСТАВЛЕНИЕ(Значение)

ИНАЧЕ Значение

КАК ОтформатированноеЗначение

ИЗ

ВашаТаблица

Пример 3: Проверка корректности данных перед загрузкой

Задача: валидировать данные из внешнего источника перед записью в 1С.

ВЫБРАТЬ

ЕСТЬNULL(ВЫРАЗИТЬ(ВнешнееПоле КАК ЧИСЛО), 0) КАК ЧисловоеЗначение,

ЕСТЬNULL(ВЫРАЗИТЬ(ВнешнееПоле КАК ДАТА), ДАТАВРЕМЯ(1, 1, 1)) КАК ДатаЗначение

ИЗ

ВнешниеДанные

💡

Для ссылочных типов всегда используйте МЕТАДАННЫЕ() — это единственный надёжный способ отличить их от обычных строк. Функции ТИП() и ТИПЗНАЧЕНИЯ() здесь бесполезны.

FAQ: Частые вопросы по определению типов в запросах 1С

Можно ли в одном запросе проверить тип поля и сразу привести его к нужному формату?

Да, используйте вложенные функции. Например, чтобы получить дату из строки или NULL, если приведение невозможно:

ВЫБРАТЬ

ВЫРАЗИТЬ(ЕСТЬNULL(СтрокаДаты, "") КАК ДАТА) КАК ДатаИлиNULL

Если СтрокаДаты не является корректной датой, вернётся NULL.

Как отличить пустую строку от NULL в запросе?

Используйте функцию ЗНАЧЕНИЕЗАПОЛНЕНО():

ВЫБРАТЬ

ВЫБОР

КОГДА Значение ЕСТЬ NULL ТОГДА "NULL"

КОГДА НЕ ЗНАЧЕНИЕЗАПОЛНЕНО(Значение) ТОГДА "Пустая строка"

ИНАЧЕ "Непустое значение"

КАК СтатусПоля

ИЗ

ВашаТаблица

Почему МЕТАДАННЫЕ() возвращает NULL для некоторых полей?

Это означает, что поле не является ссылочным типом. МЕТАДАННЫЕ() работает только со ссылками на объекты метаданных (справочники, документы и т.д.). Для примитивных типов (числа, строки) функция вернёт NULL.

Как определить тип поля в динамическом запросе, где имя поля заранее неизвестно?

Используйте конструкцию с параметром и функцией ТИП():

ТекстЗапроса = "ВЫБРАТЬ ТИП(&Поле) КАК ТипПоля ИЗ ВашаТаблица";

Запрос = Новый Запрос(ТекстЗапроса);

Запрос.УстановитьПараметр("Поле", ИмяПоля); // ИмяПоля - строка с именем поля

Результат = Запрос.Выполнить();

Для ссылочных полей аналогично используйте МЕТАДАННЫЕ(&Поле).

Можно ли в запросе получить список всех типов полей таблицы?

Нет, в чистом SQL-запросе это невозможно. Однако вы можете:

  1. Сформировать запрос динамически, перебирая все поля таблицы.
  2. Использовать Метаданные.Таблицы.ВашаТаблица.Реквизиты в модуле для получения структуры.
  3. Для ссылочных полей использовать МЕТАДАННЫЕ() в цикле по всем колонкам.