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

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

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

Как найти битую ссылку в запросе 1С: проверка через ЕСТЬ NULL, соединение с таблицей, поиск по представлению «Объект не найден». Примеры кода и типичные ошибки.

Битая ссылка в 1С — это ссылка на объект, который был удалён из базы, но на который продолжают ссылаться другие объекты или записи регистров. В запросе такая ссылка ведёт себя коварно: она не равна NULL, не является пустой ссылкой, но при обращении к её реквизитам вы получаете NULL, а при попытке получить объект через ПолучитьОбъект() — ошибку или значение Неопределено.

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

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

Битая ссылка возникает, когда объект удаляют физически (например, непосредственным удалением без контроля ссылочной целостности, в ходе обмена или при свёртке базы), а записи в других таблицах продолжают хранить его уникальный идентификатор. Платформа 1С при выводе такой ссылки показывает строку вида <Объект не найден> (84:b2a8...).

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

Способ 1. Левое соединение и проверка ЕСТЬ NULL

Основной и самый надёжный метод — соединить проверяемую таблицу с таблицей-источником ссылки левым соединением. Если объект существует, соединение подтянет его ключевое поле; если объект удалён, поле будет NULL.

ВЫБРАТЬ

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

Реализация.Контрагент КАК КонтрагентСсылка

ИЗ

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

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

ПО Реализация.Контрагент = Контрагенты.Ссылка

ГДЕ

Контрагенты.Ссылка ЕСТЬ NULL

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

Второе условие важно: пустая ссылка тоже не найдётся в таблице справочника, поэтому без него вы получите ложные срабатывания на документах, где поле просто не заполнено. Всегда исключайте и NULL, и пустые ссылки из выборки.

Если реквизит составного типа (например, «Плательщик» может быть контрагентом или организацией), соединение нужно делать с каждой возможной таблицей и проверять, что все соединения дали NULL, при этом тип значения соответствует проверяемой таблице.

Способ 2. Проверка реквизита ссылки на NULL

Быстрый вариант без явного соединения — обратиться к любому реквизиту ссылки через точку и проверить его на NULL. Платформа неявно выполнит то же левое соединение.

ВЫБРАТЬ

Заказ.Ссылка КАК Заказ

ИЗ

Документ.ЗаказКлиента КАК Заказ

ГДЕ

Заказ.Менеджер.Наименование ЕСТЬ NULL

И НЕ Заказ.Менеджер = ЗНАЧЕНИЕ(Справочник.Пользователи.ПустаяСсылка)

И НЕ Заказ.Менеджер ЕСТЬ NULL

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

Способ 3. Поиск по представлению «Объект не найден»

Если битая ссылка уже попала в результат запроса или в отчёт, её можно распознать по строковому представлению. В запросе для этого используют функцию ПРЕДСТАВЛЕНИЕ() и сравнение по шаблону:

ВЫБРАТЬ

Док.Ссылка КАК Документ

ИЗ

Документ.ПоступлениеТоваровУслуг КАК Док

ГДЕ

ПРЕДСТАВЛЕНИЕ(Док.Склад) ПОДОБНО "%Объект не найден%"

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

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

Сравнение вариантов

Левое соединение + ЕСТЬ NULL

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

Реквизит через точку + ЕСТЬ NULL

Короткая запись без соединения. Минусы: неявные соединения и риск ложных срабатываний на реквизитах, допускающих NULL.

ПРЕДСТАВЛЕНИЕ + ПОДОБНО

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

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

Точная проверка на встроенном языке. Не подходит для пакетной обработки больших выборок из-за пообъектного обращения к БД.

Поиск битых ссылок в регистрах и составных типах

В регистрах сведений и накопления битые ссылки встречаются в измерениях и реквизитах чаще, чем в документах, особенно после обменов. Логика проверки та же: левое соединение таблицы регистра с таблицей измерения по полю ссылки и условие ЕСТЬ NULL.

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

ВЫБРАТЬ

Записи.Регистратор КАК Регистратор,

Записи.Аналитика КАК Аналитика

ИЗ

РегистрСведений.ЦеныНоменклатуры КАК Записи

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

ПО (ВЫРАЗИТЬ(Записи.Аналитика КАК Справочник.Номенклатура)) = Товары.Ссылка

ГДЕ

ТИПЗНАЧЕНИЯ(Записи.Аналитика) = ТИП(Справочник.Номенклатура)

И Товары.Ссылка ЕСТЬ NULL

Порядок действий
  1. 1
    Определите поле, в котором подозреваете битую ссылку, и таблицу-источник этого типа
  2. 2
    Напишите запрос с левым соединением и условием ЕСТЬ NULL по полю Ссылка источника
  3. 3
    Исключите из выборки пустые ссылки и NULL-значения самого поля
  4. 4
    Выполните запрос в консоли запросов на копии базы и проанализируйте результат
  5. 5
    Проверьте найденные записи: откройте объект и убедитесь, что ссылка отображается как «Объект не найден»
  6. 6
    Только после резервного копирования решайте, как исправлять: восстановление объекта, замена ссылки или очистка поля

Проверка результата и что делать с найденными ссылками

После выполнения запроса убедитесь, что найденные записи действительно содержат битые ссылки: откройте объект-владелец в режиме предприятия — поле должно отображаться как «<Объект не найден>». Если поле выглядит пустым, значит, сработало условие на незаполненное значение и запрос нужно скорректировать.

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

Типичные ошибки
01
Проверять ссылку только на NULL: битая ссылка не равна NULL, и такой запрос ничего не найдёт
02
Забыть исключить пустые ссылки: все незаполненные поля попадут в результат как ложные срабатывания
03
Использовать ПОДОБНО по представлению в регламентных заданиях: запрос работает медленно и ломается при смене языка платформы
04
Исправлять битые ссылки прямой записью в рабочей базе без копии: при ошибке данные восстановить будет нечем
05
Проверять только документы: битые ссылки чаще всего прячутся в измерениях регистров и табличных частях

Частые ошибки и ограничения методов

Главная ошибка — путать битую ссылку с NULL и пустой ссылкой. Это три разных состояния: NULL означает отсутствие значения в поле, пустая ссылка — существующее «нулевое» значение типа, а битая ссылка — несуществующий объект с реальным идентификатором. Корректный запрос обрабатывает все три случая отдельно.

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

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

Итог

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

Битая ссылка не равна NULL и не равна пустой ссылке. Надёжный способ поиска в запросе — левое соединение с таблицей-источником и условие ЕСТЬ NULL по полю Ссылка с исключением пустых значений. Исправления выполняйте только на копии базы после проверки результата.

FAQ

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

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

Можно ли найти битые ссылки без запроса, штатными средствами?

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

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

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

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

Сравните ссылку с пустой и, если она заполнена, вызовите Ссылка.ПолучитьОбъект(). Если метод вернул Неопределено — объект удалён, ссылка битая. Способ точный, но медленный для массовой проверки, поэтому для больших выборок лучше использовать запрос с соединением.

Опасно ли оставлять битые ссылки в базе?

Сами по себе они не разрушают базу, но вызывают ошибки в отчётах, обменах и проведении документов, а также искажают итоги, когда соединения с несуществующими объектами отсекают строки. Регулярное появление битых ссылок — признак нарушения процедур удаления данных, и источник нужно устранять.