Разработка и Конфигурация · 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
- 1Определите поле, в котором подозреваете битую ссылку, и таблицу-источник этого типа
- 2Напишите запрос с левым соединением и условием ЕСТЬ NULL по полю Ссылка источника
- 3Исключите из выборки пустые ссылки и NULL-значения самого поля
- 4Выполните запрос в консоли запросов на копии базы и проанализируйте результат
- 5Проверьте найденные записи: откройте объект и убедитесь, что ссылка отображается как «Объект не найден»
- 6Только после резервного копирования решайте, как исправлять: восстановление объекта, замена ссылки или очистка поля
Проверка результата и что делать с найденными ссылками
После выполнения запроса убедитесь, что найденные записи действительно содержат битые ссылки: откройте объект-владелец в режиме предприятия — поле должно отображаться как «<Объект не найден>». Если поле выглядит пустым, значит, сработало условие на незаполненное значение и запрос нужно скорректировать.
Вариантов исправления три. Первый — восстановить удалённый объект, если есть его данные из архивной копии или узла обмена. Второй — заменить битую ссылку на существующий объект (например, на специально созданный элемент «Не указан»). Третий — очистить поле, если бизнес-логика допускает пустое значение. Любой из вариантов применяйте только после анализа, куда ещё ссылается этот идентификатор.
Частые ошибки и ограничения методов
Главная ошибка — путать битую ссылку с NULL и пустой ссылкой. Это три разных состояния: NULL означает отсутствие значения в поле, пустая ссылка — существующее «нулевое» значение типа, а битая ссылка — несуществующий объект с реальным идентификатором. Корректный запрос обрабатывает все три случая отдельно.
Второе ограничение касается производительности. Левое соединение по ссылочному полю на больших таблицах требует индекса по этому полю; для стандартных реквизитов индексы обычно есть, а для неиндексированных реквизитов регистров запрос может выполняться долго. Для тяжёлых баз запускайте такие проверки в нерабочее время или на копии.
Наконец, помните, что запрос показывает состояние «здесь и сейчас». Если битые ссылки появляются регулярно, ищите источник: непосредственное удаление объектов, обработки обмена без контроля целостности или устаревшие процедуры свёртки. Устранение причины важнее разовой чистки.
Что важно запомнить
Битая ссылка не равна NULL и не равна пустой ссылке. Надёжный способ поиска в запросе — левое соединение с таблицей-источником и условие ЕСТЬ NULL по полю Ссылка с исключением пустых значений. Исправления выполняйте только на копии базы после проверки результата.
FAQ
Чем битая ссылка отличается от пустой ссылки?
Пустая ссылка — это штатное «нулевое» значение ссылочного типа, объект для него в таблице не требуется. Битая ссылка хранит идентификатор реально существовавшего, но удалённого объекта. В запросе пустая ссылка сравнивается с ЗНАЧЕНИЕ(...ПустаяСсылка), а битая выявляется только через соединение с таблицей-источником.
Можно ли найти битые ссылки без запроса, штатными средствами?
Да. В типовых конфигурациях есть обработки поиска и удаления помеченных объектов, которые контролируют ссылочную целостность, а тестирование и исправление информационной базы включает проверку ссылочной целостности. Однако эти инструменты не всегда показывают, где именно лежит битая ссылка, — запрос даёт точный список записей.
Почему запрос с условием «Ссылка ЕСТЬ NULL» не находит битые ссылки?
Потому что само поле ссылки физически заполнено — в нём лежит идентификатор. NULL появляется только в полях соединённой таблицы, когда объект по этому идентификатору не найден. Проверять на NULL нужно поле Ссылка таблицы-источника после левого соединения, а не само проверяемое поле.
Как проверить битую ссылку программно, без запроса?
Сравните ссылку с пустой и, если она заполнена, вызовите Ссылка.ПолучитьОбъект(). Если метод вернул Неопределено — объект удалён, ссылка битая. Способ точный, но медленный для массовой проверки, поэтому для больших выборок лучше использовать запрос с соединением.
Опасно ли оставлять битые ссылки в базе?
Сами по себе они не разрушают базу, но вызывают ошибки в отчётах, обменах и проведении документов, а также искажают итоги, когда соединения с несуществующими объектами отсекают строки. Регулярное появление битых ссылок — признак нарушения процедур удаления данных, и источник нужно устранять.