В практике разработчика 1С нередко возникают ситуации, которые кажутся магическими: запрос, написанный абсолютно корректно, отказывается возвращать данные при поиске по конкретному идентификатору, хотя визуально в базе данных запись присутствует. Особенно часто это проявляется при работе с СУБД PostgreSQL и использовании расширений конфигурации. В этой статье мы подробно разберем, почему поиск по выражению (GUID) может не работать, как платформа 1С хранит ссылки и на что обратить внимание при отладке подобных «загадочных» запросов.
Рассмотрим типичную ситуацию. Программист выполняет запрос к Регистру Сведений, используя параметр &Сотрудник. При интерактивном выборе сотрудника в консоли запросов («по значению») данные находятся. Однако, если тот же запрос запустить программно или указать идентификатор через выражение Новый УникальныйИдентификатор("..."), результат оказывается пустым.
Проанализируем пример кода, который часто становится источником ошибки:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| АШ_СвязьВидовРаботИСотрудников.Сотрудник КАК Сотрудник,
| АШ_СвязьВидовРаботИСотрудников.ВидРабот КАК ВидРабот
|ИЗ
| РегистрСведений.АШ_СвязьВидовРаботИСотрудников КАК АШ_СвязьВидовРаботИСотрудников
|ГДЕ
| АШ_СвязьВидовРаботИСотрудников.Сотрудник = &Сотрудник";
// Попытка получить ссылку по известному GUID
НужныйGUID = Новый УникальныйИдентификатор("3C8F410C-B0E7-11ED-9870-244BFE534578");
Запрос.УстановитьПараметр("Сотрудник", Справочники.Сотрудники.ПолучитьСсылку(НужныйGUID));
РезультатЗапроса = Запрос.Выполнить();
На первый взгляд всё верно. Но именно здесь кроется главная ловушка платформы 1С. Метод ПолучитьСсылку() работает «вслепую». Он всегда возвращает объект типа «ссылка» с указанным идентификатором, даже если в самой базе данных (в таблице справочника) объекта с таким GUID никогда не существовало. Это так называемая «битая ссылка» или «ссылка-фантом».
Важно понимать, что строковое представление GUID в 1С (например, 3C8F410C...) и то, как этот идентификатор физически записан в таблицах PostgreSQL — это разные вещи. Рассмотрим основные причины несовпадения:
_IDRRef или поля ссылок в регистрах), платформа 1С выполняет перестановку байтов. Если вы пытаетесь искать данные напрямую в СУБД, простое копирование строки из 1С не поможет — порядок групп разрядов будет другим.Выясним причину, по которой запрос не видит данные. Первым делом необходимо проверить, совпадает ли идентификатор у найденного в базе объекта с тем, который мы используем в коде. Для этого в консоли кода выполним следующую проверку:
// Возьмем ссылку сотрудника, который точно есть в регистре
ЗаписьРегистра = РегистрыСведений.АШ_СвязьВидовРаботИСотрудников.Выбрать();
Если ЗаписьРегистра.Следующий() Тогда
СотрудникОбъект = ЗаписьРегистра.Сотрудник;
Сообщить("ФИО: " + СотрудникОбъект);
Сообщить("Реальный GUID в базе: " + СотрудникОбъект.УникальныйИдентификатор());
КонецЕсли;
Сравните полученную строку с той, что вы используете в Новый УникальныйИдентификатор(). Как показывает практика, часто обнаруживается различие даже в одном символе, что делает ссылки абсолютно разными для базы данных.
Если данные хранятся в объектах, добавленных через расширения, ситуация усложняется. В PostgreSQL для расширений создаются дополнительные таблицы (например, с суффиксом _X1). Платформа выполняет соединение (JOIN) основной таблицы и таблицы расширения «на лету».
Рассмотрим особенности работы с расширениями:
_X1 могут быть потеряны или стать недоступными. Убедитесь, что расширение активно и корректно подключено для текущего пользователя.Проанализируем ситуацию, когда поле в регистре имеет составной тип данных. В SQL-структуре это приводит к созданию нескольких колонок (для типа и для самой ссылки). При поиске «по выражению» через сторонние инструменты или некорректно настроенные консоли, может возникнуть ошибка сопоставления типов.
В коде 1С всегда следует явно приводить типы или убеждаться, что передаваемый параметр соответствует типу измерения регистра:
// Хорошая практика - явная проверка типа перед установкой параметра
Если ТипЗнч(Объект.Сотрудник) = Тип("СправочникСсылка.Сотрудники") Тогда
Запрос.УстановитьПараметр("Сотрудник", Объект.Сотрудник);
Иначе
// Обработка ошибки
КонецЕсли;
Если вы столкнулись с тем, что запрос «не видит» существующую запись по ссылке, выполните следующие действия:
GUID непосредственно из объекта, который записан в проблемной строке регистра, используя метод Ссылка.УникальныйИдентификатор()._IDRRef.ANALYZE для таблиц регистра и справочника, чтобы планировщик запросов корректно обрабатывал индексы.Помните, что Уникальный Идентификатор — это «паспорт» объекта в системе. Тот факт, что два объекта называются одинаково, не делает их равными для запроса. Внимательная проверка реальных идентификаторов через отладку — кратчайший путь к решению подобных загадок.