Разработчики платформы 1С:Предприятие часто сталкиваются с ситуацией, когда необходимо программно определить природу хранимых в базе данных объектов непосредственно на уровне СУБД. Запросы в 1С обладают мощным синтаксисом, но прямая функция вроде ТИПЗНАЧЕНИЯ в языке запросов отсутствует по умолчанию, в отличие от встроенного языка. Это создает определенные сложности при формировании отчетов или выборке разнородных данных. Тем не менее, существуют проверенные временем приемы, позволяющие обойти это ограничение.

Понимание механизма работы типов в запросах критически важно для оптимизации производительности. Неправильная попытка привести разнородные данные к одному типу может привести к ошибкам выполнения или значительному замедлению выборки. В этой статье мы детально рассмотрим методы определения типа ссылок, значений перечислений и примитивных типов данных.

Мы разберем как стандартные, так и нетривиальные подходы, включая использование виртуальных таблиц и системных полей. Вы узнаете, как безопасно работать с колонками, содержащими значения разных типов, и как избежать типичных ошибок при кастинге данных.

Особенности типизации в языке запросов 1С

Язык запросов 1С строго типизирован, однако эта типизация работает иначе, чем во встроенном языке. В запросе каждая колонка результата должна иметь четко определенный тип данных. Если вы пытаетесь выбрать поле, которое в разных записях может содержать ссылку на Справочник или Число, движок запросов потребует явного приведения типов.

Основная сложность заключается в том, что платформа хранит информацию о типе значения в служебных структурах данных, которые не всегда доступны напрямую через стандартный синтаксис SELECT. Для разработчика это означает, что нельзя просто написать ВЫБРАТЬ ТИП(Поле). Необходимо использовать обходные пути, которые эмулируют проверку типа.

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

⚠️ Внимание: Попытка привести значение типа СправочникСсылка к типу Число без предварительной проверки приведет к ошибке выполнения запроса "Неверный тип значения". Всегда проверяйте совместимость типов перед агрегацией данных.

Использование функции ТИПЗНАЧЕНИЯ в выражениях

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

Синтаксис использования достаточно прост, но требует внимательности к деталям. Функция применяется к конкретному полю или выражению. Результатом будет строка, которую можно использовать в условиях отбора ГДЕ или в псевдонимах колонок.

ВЫБРАТЬ

Ссылка,

ТИПЗНАЧЕНИЯ(Ссылка) КАК ТипСсылки

ИЗ

Справочник.Номенклатура

Однако есть важный нюанс: функция ТИПЗНАЧЕНИЯ в запросе работает не для всех типов данных одинаково эффективно. Для ссылок она возвращает полный тип, включая имя объекта метаданных. Для примитивных типов результат может отличаться в зависимости от контекста выполнения запроса.

💡

Если функция ТИПЗНАЧЕНИЯ возвращает пустую строку для некоторых записей, проверьте, не является ли значение NULL. Пустые значения в 1С часто требуют отдельной обработки через функцию ЕСТЬNULL().

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

Эмуляция проверки типа через оператор ВЫБОР

В случаях, когда прямая функция типа недоступна или работает некорректно, классическим решением является использование составного оператора ВЫБОР. Этот метод основан на попытке приведения значения к заведомо несовместимому типу и перехвате результата. Логика строится на том, что успешное приведение говорит об одном типе, а ошибка (которую мы эмулируем логически) — о другом.

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

  • 🔍 Проверяем наличие поля ИНН — если есть, это скорее всего юридическое лицо.
  • 🔍 Проверяем поле ДатаДоговора — наличие указывает на тип Договор.
  • 🔍 Используем функцию ЕСТЬNULL для проверки специфических реквизитов.

Пример реализации через ВЫБОР выглядит следующим образом:

ВЫБРАТЬ

ВЫБОР

КОГДА Договор.Период ЕСТЬ NULL ТОГДА "Справочник"

ИНАЧЕ "Договор"

КОНЕЦ КАК ТипОбъекта

ИЗ

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

ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ДоговорыКонтрагентов КАК Договор

ПО Документ.Договор = Договор.Ссылка

Такой подход требует знания структуры метаданных. Вы должны точно знать, какие реквизиты уникальны для каждого типа объекта. Это делает код менее универсальным, но более быстрым в выполнении, так как не требует вызова тяжелых функций мета-информации.

📊 Какой метод определения типа вы используете чаще?
ТИПЗНАЧЕНИЯ()
Оператор ВЫБОР
Программная обработка
Виртуальные таблицы

Работа с таблицей значений и типами данных

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

Чтобы корректно получить тип в запросе к таблице значений, часто приходится использовать временные таблицы. Вы загружаете данные, явно указывая типы колонок, а затем в запросе к временной таблице используете стандартные методы проверки. Это добавляет overhead по памяти, но гарантирует стабильность работы.

Важно помнить про ограничение на размер строки при использовании широких типов данных. Если вы пытаетесь привести все возможные типы к строке для унификации, вы можете столкнуться с усечением данных.

Тип данных в ТЗ Возможность определения в запросе Рекомендуемый метод
Число Высокая Прямая проверка диапазона
Строка Высокая Функция ДЛИНА()
Дата Средняя Сравнение с '0001-01-01'
Булево Низкая Приведение к числу (0/1)

Особое внимание стоит уделить колонкам типа ХранилищеЗначения. В запросе они часто отображаются как бинарные данные, и определить тип вложенного объекта без выгрузки в переменную встроенного языка практически невозможно.

Системные поля и виртуальные таблицы типов

Платформа 1С предоставляет доступ к системной информации через специальные виртуальные таблицы. Одним из мощных инструментов является работа с таблицей Система.ТипыЗначений или аналогичными служебными объектами (в зависимости от конкретной конфигурации и версии платформы).

Эти таблицы содержат маппинг внутренних идентификаторов типов и их строковых представлений. Используя соединения с этими таблицами, можно получить каноническое имя типа для любого значения. Это особенно полезно при построении динамических отчетов, где структура данных заранее неизвестна.

⚠️ Внимание: Структура системных таблиц может изменяться при обновлении платформы. Не рекомендуется жестко привязываться к именам полей системных таблиц в производственном коде без проверки совместимости.

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

Секрет оптимизации

При частом обращении к определению типов создайте постоянную временную таблицу с кэшем соответствий "ВнутреннийКодТипа" - "ИмяТипа". Это ускорит выполнение запросов в 3-5 раз.

Обработка ошибок и исключительных ситуаций

Даже при использовании всех описанных методов, риск возникновения ошибок остается. Запрос может завершиться аварийно, если встретится значение, которое невозможно обработать выбранным методом. Например, попытка получить длину у значения типа БитоваяПоля вызовет исключение.

Встроенными средствами языка запросов перехватить такую ошибку внутри самого запроса нельзя. Обработка должна производиться на уровне кода 1С, оборачивающего выполнение запроса в блок Попытка...Исключение. Это позволяет логировать проблемные записи и продолжать работу.

  • ✅ Всегда проверяйте запрос на тестовой базе перед запуском на продуктиве.
  • ✅ Используйте ЕСТЬNULL для фильтрации некорректных данных до проверки типа.
  • ✅ Разбивайте сложные запросы на этапы с использованием временных таблиц.

Если вы работаете с конфигурациями, где типы полей могут меняться динамически (например, дополнительные реквизиты с разным типом), обязательно предусматривайте ветку логики для "Неизвестного типа".

💡

Надежность определения типа в запросе напрямую зависит от однородности данных в выборке. Чем чище данные, тем проще и быстрее работает запрос.

Часто задаваемые вопросы (FAQ)

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

Да, можно. Методы аналогичны работе со справочниками. Используйте функцию ТИПЗНАЧЕНИЯ или оператор ВЫБОР для полей измерений и ресурсов. Однако помните, что в регистрах сведений типы ресурсов фиксированы метаданными.

Почему ТИПЗНАЧЕНИЯ возвращает пустую строку?

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

Как определить тип в запросе СКД (Система Компоновки Данных)?

В СКД прямое использование функций языка запросов ограничено. Рекомендуется выносить логику определения типа в отдельный запрос-источник данных, а в СКД использовать уже готовое поле с определенным типом.

Влияет ли определение типа на производительность запроса?

Да, существенно. Функции мета-информации и сложные операторы ВЫБОР с множеством условий могут замедлить выполнение запроса на 20-40%. Используйте кэширование результатов во временные таблицы при повторяющихся обращениях.

☑️ Готовность к внедрению

Выполнено: 0 / 4