При переходе на платформу 1С:Предприятие 8.3 многие разработчики столкнулись с появлением нового системного реквизита — ИмяПредопределенныхДанных. На первый взгляд кажется, что это обычная строка, содержащая имя элемента из конфигуратора, но при попытке использовать её в сложных запросах платформа накладывает жесткие ограничения. Мы часто сталкиваемся с тем, что это поле нельзя использовать в строковых функциях или при определенных типах соединений. В этой статье мы подробно разберем, почему так происходит, как работает механизм связи с метаданными и как извлечь реальную пользу из этого реквизита.
Для начала проанализируем, зачем вообще понадобилось это поле. До версии 8.3 связь между объектом в базе данных и объектом в конфигураторе (предопределенным элементом) осуществлялась жестко по внутреннему идентификатору (GUID). Это вызывало огромные сложности при обновлении конфигураций и в распределенных информационных базах (РИБ). Поле ИмяПредопределенныхДанных было введено, чтобы "отвязать" логическое имя элемента от его физического ID.
Важный нюанс: хотя в интерфейсе "1С:Предприятие" это поле выглядит как текстовое, на уровне СУБД (SQL) оно является индексированным служебным полем. Платформа воспринимает его не как произвольную строку, а как ключ связи. Именно поэтому мы не можем применять к нему операторы ПОДОБНО, функции ПОДСТРОКА или конкатенацию. Платформа ожидает только операции прямого сравнения, так как это позволяет эффективно использовать индексы базы данных.
Рассмотрим распространенное заблуждение о том, что это поле бесполезно в секции ГДЕ. На самом деле, поле ИмяПредопределенныхДанных отлично работает в условиях отбора, если мы передаем туда конкретное значение или параметр. Посмотрим на пример кода, который позволяет выбрать ссылку по её имени в конфигураторе:
ВЫБРАТЬ
Контрагенты.Ссылка КАК Ссылка
ИЗ
Справочник.Контрагенты КАК Контрагенты
ГДЕ
Контрагенты.ИмяПредопределенныхДанных = &ИмяПредопределенныхДанных
Такой подход удобен, когда нам нужно программно найти элемент, имя которого мы знаем только в виде строки (например, при загрузке настроек из внешнего файла или макета). Это гораздо производительнее, чем перебор всех элементов в цикле или использование функции НайтиПоНаименованию.
Одной из самых полезных практик использования этого реквизита является поиск и устранение дублей. Иногда в базе данных из-за ошибок обмена или некорректного обновления возникают ситуации, когда два разных элемента (с разными ссылками) претендуют на одно и то же имя предопределенного. Мы можем найти такие записи, выполнив внутреннее соединение таблицы самой с собой по этому полю.
Разберем конкретный алгоритм очистки дублей, представленный на практике:
Процедура ОчиститьДублиПредопределенныхЭлементов()
Запрос = Новый Запрос(
"ВЫБРАТЬ
| СсылкиДляФорм.Ссылка КАК ИнформационнаяСсылка
|ИЗ
| Справочник.ИнформационныеСсылкиДляФорм КАК СсылкиДляФорм
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.ИнформационныеСсылкиДляФорм КАК СсылкиДляФорм1
| ПО СсылкиДляФорм.ИмяПредопределенныхДанных = СсылкиДляФорм1.ИмяПредопределенныхДанных
| И СсылкиДляФорм.Ссылка <> СсылкиДляФорм1.Ссылка
|ГДЕ
| СсылкиДляФорм1.ИмяПредопределенныхДанных <> """"");
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
// Получаем объект для редактирования
ОбъектСсылка = Выборка.ИнформационнаяСсылка.ПолучитьОбъект();
// Разрываем связь с метаданными, очищая имя
ОбъектСсылка.ИмяПредопределенныхДанных = "";
ОбъектСсылка.ПометкаУдаления = Истина;
// Используем ОбменДанными.Загрузка, чтобы обойти проверки
ОбъектСсылка.ОбменДанными.Загрузка = Истина;
ОбъектСсылка.Записать();
КонецЦикла;
КонецПроцедуры
В данном примере мы находим все элементы, у которых совпадает ИмяПредопределенныхДанных, но различаются ссылки. После чего мы программно "отвязываем" дублирующий элемент от метаданных, просто присваивая полю пустую строку. Это превращает предопределенный элемент в обычный, после чего его можно пометить на удаление.
Давайте выясним причину, по которой этот реквизит доступен для записи. Это дает разработчику мощный инструмент управления данными без изменения конфигурации:
ЗНАЧЕНИЕ(...) в запросах), вы можете просто записать в его поле ИмяПредопределенныхДанных соответствующее имя из метаданных.ИмяПредопределенныхДанных позволит платформе правильно сопоставить их при синхронизации.Проанализируем способы получения имени предопределенного элемента в коде. Помимо прямого обращения через точку (Ссылка.ИмяПредопределенныхДанных), существует метод менеджера: Справочники.Контрагенты.ПолучитьИмяПредопределенного(Ссылка).
Рекомендация по производительности: Всегда отдавайте предпочтение методу менеджера ПолучитьИмяПредопределенного(), если вам нужно узнать имя в коде. Платформа кэширует эти данные, и такое обращение не всегда вызывает реальный запрос к базе данных, в отличие от обращения к реквизиту через точку, которое всегда тянет данные объекта.
Важно не путать эти два понятия, которые часто встречаются в конструкторе запросов:
Булево) — отвечает на вопрос "Является ли этот элемент системным в данный момент?". Оно возвращает Истина, если поле с именем заполнено и корректно связано.Строка) — это конкретный "ключ", который связывает запись в таблице СУБД с идентификатором в программном коде конфигурации.Таким образом, мы видим, что ИмяПредопределенныхДанных — это не просто "бесполезная строка", а ключевой механизм платформы 8.3 для обеспечения гибкости и стабильности данных. Несмотря на ограничения в запросах (связанные с особенностями индексации в СУБД, такими как PostgreSQL или MS SQL), этот реквизит остается единственным легальным способом управления "предопределенностью" объектов в реальном времени.