В практике разработчика 1С периодически возникает задача быстрого получения значений всех констант системы. Это может потребоваться для создания отчетов по настройкам, проведения аудита базы данных или при реализации механизмов миграции данных. Однако при попытке объединить значения разных констант в одну колонку запроса программисты часто сталкиваются с ошибкой «Несовместимые типы ОБЪЕДИНИТЬ». Особенно остро эта проблема проявляется, когда среди констант встречаются строки неограниченной длины, числа и ссылки.
В этой статье мы подробно разберем, почему возникает эта ошибка, как устроена таблица констант в базе данных и какие существуют способы для корректного вывода всех значений в единый список.
Для начала проанализируем, как 1С хранит константы на уровне базы данных. В отличие от справочников или документов, все константы хранятся в одной единственной таблице. В этой таблице всегда присутствует только одна строка, а каждая колонка соответствует отдельной константе. Когда мы пишем запрос к конкретной константе, платформа обращается к этой специфической таблице.
Основная сложность возникает при использовании оператора ОБЪЕДИНИТЬ (или UNION). Согласно правилам языка запросов 1С, типы данных в выбираемых колонках во всех частях объединения должны быть совместимы. Если в первой части запроса вы выбираете числовую константу, а во второй — строковую, система выдаст ошибку. Ситуация осложняется «длинными» строками (неограниченной длины), которые платформа не может напрямую объединять с другими типами данных без явного приведения.
Если нам необходимо получить список констант «вертикально» (одна константа — одна строка результата), мы должны привести все значения к одному общему типу, чаще всего к строке. Рассмотрим, как это сделать правильно, чтобы избежать ошибок с полями неограниченной длины.
Для констант с типом «Строка (неограниченная длина)» обязательно использование функции ВЫРАЗИТЬ. Важно помнить, что при приведении к строке в запросе мы должны указать максимальную длину (не более 1024 символов для платформы 1С).
Разберем пример построения такого запроса:
ВЫБРАТЬ
"АдресДляВосстановленияПароля" КАК ИмяКонстанты,
ВЫРАЗИТЬ(Константы.АдресДляВосстановленияПароляУчетнойЗаписи КАК СТРОКА(1000)) КАК Значение
ИЗ
Константы КАК Константы
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
"ВалютаУчета",
ВЫРАЗИТЬ(Константы.ВалютаУчета КАК СТРОКА(100))
ИЗ
Константы КАК Константы
Обратите внимание на использование ОБЪЕДИНИТЬ ВСЕ вместо ОБЪЕДИНИТЬ. Оператор ОБЪЕДИНИТЬ ВСЕ работает быстрее, так как не выполняет проверку на дубликаты строк, что в случае с константами абсолютно оправдано.
Иногда самым простым и эффективным способом является получение всех констант одной строкой. Поскольку в таблице констант всегда всего одна запись, мы можем извлечь её целиком. Это избавляет нас от проблем с типами данных и необходимостью использования UNION.
Рассмотрим этот подход. В коде 1С это будет выглядеть следующим образом:
Запрос = Новый Запрос("ВЫБРАТЬ * ИЗ Константы");
РезультатЗапроса = Запрос.Выполнить();
Если Не РезультатЗапроса.Пустой() Тогда
Выборка = РезультатЗапроса.Выбрать();
Выборка.Следующий();
Для Каждого Колонка Из РезультатЗапроса.Колонки Цикл
ИмяКонстанты = Колонка.Имя;
Значение = Выборка[ИмяКонстанты];
Сообщить(ИмяКонстанты + ": " + Значение);
КонецЦикла;
КонецЕсли;
Преимущества этого метода:
Если вам все же нужно объединение (например, для сложного отчета в СКД), но вы хотите сохранить исходные типы (числа как числа, даты как даты), используйте метод «разрядной сетки». Для каждого типа данных создается своя колонка, а в остальных частях объединения в эти колонки подставляется NULL.
Проанализируем пример такого запроса:
ВЫБРАТЬ
"ОсновнаяВалюта" КАК Имя,
Константы.ВалютаУчета КАК ЗначениеСсылка,
0 КАК ЗначениеЧисло,
"" КАК ЗначениеСтрока
ИЗ
Константы
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
"СрокОплатыПокупателя",
ЗНАЧЕНИЕ(Справочник.Валюты.ПустаяСсылка),
Константы.СрокОплатыПокупателя,
""
ИЗ
Константы
В дальнейшем в отчете или при обработке результата вы сможете выбрать непустое значение из нужной колонки в зависимости от логики задачи.
Важно помнить, что константы с типом ХранилищеЗначения (например, логотипы организаций или сохраненные настройки) невозможно полноценно извлечь через запрос. В результате запроса для таких полей вы получите либо NULL, либо системное представление, которое нельзя преобразовать в данные. Для получения таких значений необходимо использовать объектную модель:
Значение = Константы.ИмяНужнойКонстанты.Получить();
Чтобы не перечислять сотни констант вручную, мы рекомендуем использовать программную генерацию текста запроса через коллекцию метаданных. Это наиболее профессиональный подход.
Выясним, как это реализовать:
ТекстЗапроса = "";
Для Каждого МетаКонстанта Из Метаданные.Константы Цикл
Если ТекстЗапроса <> "" Тогда
ТекстЗапроса = ТекстЗапроса + " ОБЪЕДИНИТЬ ВСЕ ";
КонецЕсли;
// Проверяем на неограниченную длину для строк
Если МетаКонстанта.Тип.СодержитТип(Тип("Строка")) Тогда
ПолеЗначения = "ВЫРАЗИТЬ(Константы." + МетаКонстанта.Имя + " КАК СТРОКА(1024))";
Иначе
ПолеЗначения = "Константы." + МетаКонстанта.Имя;
КонецЕсли;
ТекстЗапроса = ТекстЗапроса + "ВЫБРАТЬ """ + МетаКонстанта.Имя + """, " + ПолеЗначения + " ИЗ Константы";
КонецЦикла;
Этот код автоматически построит корректный запрос, учитывая особенности строковых полей и объединяя все константы в единую таблицу.
Мы рассмотрели несколько способов решения задачи. Выбор конкретного метода зависит от ваших целей:
ВЫБРАТЬ * и перебор колонок в коде для самого простого и быстрого получения всех значений.ВЫРАЗИТЬ(... КАК СТРОКА(1024)), если вам критично получить результат именно в одном столбце запроса через ОБЪЕДИНИТЬ.Метаданные.Константы для динамического формирования текста запроса.Помните об ограничениях платформы на длину строки в 1024 символа при использовании функции ВЫРАЗИТЬ и о невозможности прямой работы с двоичными данными (ХранилищемЗначения) внутри SQL-запросов 1С.