К статье
Практический материал

Разработка и Конфигурация · 11 мин

Как в запросе 1С получить битую ссылку

Как найти битую ссылку в запросе 1С: проверка через NULL, соединение с справочником, типы битых ссылок, примеры кода, типичные ошибки и способы исправления.

Битая ссылка в 1С — это значение ссылочного типа, которое указывает на объект, уже удалённый из информационной базы. Физически в поле таблицы остаётся идентификатор (GUID), но записи с таким идентификатором в таблице-владельце больше нет. При обращении к такому объекту платформа возвращает представление вида «<Объект не найден> (…): …», а попытка получить его реквизиты приводит к неочевидным ошибкам в отчётах и обработках.

Чаще всего битые ссылки появляются после прямого удаления объектов без контроля ссылочной целостности, после обменов данными, когда объект выгружен, а его владелец — нет, а также после нештатного восстановления базы из копии. Проблема особенно заметна в запросах: левое соединение с таблицей справочника или документа по такой ссылке возвращает NULL, и строки либо теряются, либо искажают итоги.

Задача «получить битую ссылку в запросе» обычно ставится двояко: либо нужно найти все записи, где ссылка битая, чтобы их исправить, либо нужно корректно обработать такие ссылки прямо в запросе, чтобы отчёт не падал и не врал. Ниже разобраны оба сценария с готовыми конструкциями языка запросов.

Что такое битая ссылка и как она выглядит в запросе

В языке запросов 1С битая ссылка ведёт себя неоднозначно. Само поле ссылки не равно NULL — в нём лежит вполне конкретный идентификатор. Но любое обращение через точку к реквизитам несуществующего объекта (разыменование) возвращает NULL, а левое соединение с таблицей объекта не находит пару и тоже даёт NULL в присоединённых полях.

Именно это свойство и используется для обнаружения. Если поле Товары.Номенклатура заполнено, но Справочник.Номенклатура.Ссылка при соединении по этому полю равно NULL — объект номенклатуры удалён, а ссылка осталась. Это и есть надёжный признак битой ссылки в запросе.

Важно отличать битую ссылку от пустой. Пустая ссылка — это допустимое значение «ничего не выбрано», оно хранится в базе и корректно сравнивается с ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка). Битая ссылка — это признак повреждения данных, и обрабатывать её нужно иначе.

Как найти битые ссылки через левое соединение

Базовый приём — левое соединение таблицы, где хранится ссылка, с таблицей объекта и проверка результата соединения на NULL. Пример для табличной части документа:

ВЫБРАТЬ

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

РеализацияТовары.Номенклатура КАК БитаяСсылка

ИЗ

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

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

ПО РеализацияТовары.Номенклатура = Номенклатура.Ссылка

ГДЕ

НЕ РеализацияТовары.Номенклатура ЕСТЬ NULL

И РеализацияТовары.Номенклатура <> ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка)

И Номенклатура.Ссылка ЕСТЬ NULL

Три условия в секции ГДЕ обязательны вместе. Первое отсекает NULL в самом поле (возможен в регистрах и составных типах), второе исключает штатные пустые ссылки, третье фиксирует отсутствие объекта в базе. Только комбинация всех трёх даёт именно битые ссылки, а не пустые значения.

Если поле имеет составной тип (например, «Субконто» в проводках или «Контрагент» с типами «Справочник.Контрагенты» и «Справочник.Организации»), соединение нужно делать с каждой таблицей из состава типа и проверять, что не нашлось ни одной пары. Для этого удобно использовать ВЫРАЗИТЬ(Поле КАК Справочник.НужныйТип) перед соединением — приведение типа отсечёт значения чужих типов, и логика проверки останется прозрачной.

Как получить битую ссылку средствами встроенного языка

Если запрос уже вернул выборку и нужно проверить каждую ссылку программно, используется метод ПолучитьОбъект(): для битой ссылки он возвращает Неопределено. Типовой фрагмент проверки:

Выборка = Запрос.Выполнить().Выбрать();

Пока Выборка.Следующий() Цикл

Если Выборка.Номенклатура.ПолучитьОбъект() = Неопределено Тогда

// Ссылка битая: объект не существует

КонецЕсли;

КонецЦикла;

Этот способ точен, но медленен на больших выборках — каждый вызов обращается к базе. Поэтому массовый поиск битых ссылок всегда делают запросом с соединением, а проверку через ПолучитьОбъект() применяют только для точечной диагностики отдельных значений.

Для комплексной проверки всей базы в типовых конфигурациях есть штатный механизм: тестирование и исправление информационной базы с включённой проверкой ссылочной целостности. Он находит битые ссылки по всем таблицам и может автоматически очищать их или создавать объекты-заглушки. Запросы нужны там, где требуется выборочный анализ или обработка внутри прикладной логики.

Способы обнаружения битых ссылок

Левое соединение в запросе

Подходит для массового поиска по конкретным полям. Быстро, но требует перечислять проверяемые таблицы вручную.

ПолучитьОбъект() в цикле

Точная точечная проверка в коде. Медленно на больших объёмах, не подходит для пакетной диагностики.

Тестирование и исправление ИБ

Проверяет всю базу целиком штатными средствами. Требует монопольного доступа и работает долго на больших базах.

Как исправить найденные битые ссылки

Найти битую ссылку — половина задачи. Дальше есть три варианта действий. Первый — очистить ссылку, записав в поле пустое значение соответствующего типа. Это уместно, когда ссылка не несёт учётного смысла, например в служебных регистрах сведений.

Второй вариант — заменить битую ссылку на специально созданный объект-заглушку, например элемент справочника «Неизвестный контрагент». Так делают, когда поле обязательно к заполнению и участвует в отчётности: итоги сохраняются, а проблемные строки видны отдельной группой.

Третий вариант — восстановить объект из резервной копии или из базы-источника обмена, если известен GUID. У битой ссылки идентификатор сохранился, и объект можно создать заново с тем же GUID через ПолучитьСсылку(Новый УникальныйИдентификатор(...)) и запись. Это самый трудоёмкий, но единственный способ вернуть реальные данные.

Типичные ошибки при работе с битыми ссылками в запросах

Самая частая ошибка — попытка найти битые ссылки условием Поле ЕСТЬ NULL без соединения. Такой запрос вернёт только строки, где поле физически пусто в составном типе, и не покажет ни одной битой ссылки, хотя визуально кажется, что проверка правильная.

Вторая ошибка — забыть исключить пустые ссылки. Условие «соединённая ссылка ЕСТЬ NULL» срабатывает и для пустых ссылок, потому что пустая ссылка не соединяется с реальными строками таблицы. Без фильтра на ПустаяСсылка в результат попадают тысячи штатных незаполненных полей, и реальные битые ссылки тонут в шуме.

Третья группа ошибок связана с составными типами: соединение только с одной таблицей из состава типа помечает «битыми» все значения других допустимых типов. И наконец, опасно сразу удалять найденные записи запросом — сначала нужно понять, почему ссылка побилась, иначе проблема воспроизведётся после очередного обмена.

Типичные ошибки
01
Проверка «Поле ЕСТЬ NULL» без соединения — битые ссылки не находятся, результат пустой или неполный
02
Отсутствие фильтра на пустую ссылку — в выборку попадают все незаполненные поля
03
Соединение не со всеми таблицами составного типа — корректные ссылки ошибочно считаются битыми
04
Массовое удаление записей с битыми ссылками без анализа причины — потеря учётных данных и повторение проблемы
Контрольные точки

Как проверить результат

Случайные записи из результата запроса
Норма

ПолучитьОбъект() возвращает Неопределено, в интерфейсе «Объект не найден»

Тревожный признак

Объект открывается и существует — значит, запрос написан с ошибкой

Количество найденных строк
Норма

Небольшое число записей, соответствующее истории удалений и обменов

Тревожный признак

Тысячи строк — вероятно, в выборку попали пустые ссылки или чужие типы

Отчёт после исправления
Норма

Нет пустых строк и меток «Объект не найден», итоги сходятся

Тревожный признак

Итоги изменились без объяснения — проверьте, что очищали именно битые ссылки

Частые вопросы

Можно ли получить битую ссылку без соединения с таблицей объекта?

Через разыменование реквизита с проверкой на NULL — частично, но этот способ ненадёжен: незаполненный реквизит реального объекта тоже даст NULL. Полноценная и однозначная проверка возможна только через соединение с таблицей-владельцем или программно через ПолучитьОбъект().

Чем битая ссылка отличается от пустой ссылки в запросе?

Пустая ссылка — штатное значение «ничего не выбрано», она сравнивается с ЗНАЧЕНИЕ(...ПустаяСсылка) и не является ошибкой. Битая ссылка указывает на удалённый объект: она не равна пустой, но не соединяется ни с одной строкой таблицы объекта и требует исправления данных.

Почему запрос с условием «Ссылка ЕСТЬ NULL» не находит битые ссылки?

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

Откуда берутся битые ссылки, если удаление проходит с контролем целостности?

Типичные источники — прямое удаление объектов внешними обработками без контроля ссылок, обмены данными, когда объект выгружен, а связанный объект нет или пришёл позже, а также восстановление базы из копии, снятой в момент незавершённой транзакции.

Как массово проверить всю базу, а не отдельные поля?

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

Можно ли восстановить объект, на который указывает битая ссылка?

Да, если известен GUID объекта и есть источник данных — резервная копия или база обмена. Объект создаётся заново с тем же уникальным идентификатором через ПолучитьСсылку() и заполняется данными из источника. Если источника нет, остаётся очистка ссылки или замена на объект-заглушку.

Итог

Что важно запомнить

Битую ссылку в запросе 1С находят левым соединением с таблицей объекта и тремя условиями: поле не NULL, поле не пустая ссылка, соединённая ссылка ЕСТЬ NULL. Само поле ссылки NULL не содержит. Массовую проверку всей базы делайте тестированием и исправлением, а любые исправления — только после резервного копирования.