Как удалить записи из регистра сведений со значениями "Объект не найден" в 1С?

Программист 1С v8.3 (Управляемые формы) 1С:Розница Торговля и дистрибуция
← На главную

При работе с базами данных 1С, особенно после переноса данных или некорректных операций, мы можем столкнуться с ситуацией, когда в регистрах сведений, документах или других объектах появляются ссылки на объекты, которые фактически были удалены из базы. Такие ссылки отображаются в интерфейсе как "Объект не найден", и напрямую удалить их бывает непросто, поскольку они не равны NULL или Неопределено в привычном понимании. В этой статье мы подробно разберем, как эффективно найти и удалить такие записи из регистра сведений, используя различные методы.

Наш конкретный случай касается регистра сведений "Штрихкоды" в базе 1С:Розница, где поле "Владелец" (которое может быть составного типа и ссылаться, например, на Справочник.Номенклатура) содержит битые ссылки.

Понимание природы "Объект не найден" и почему работает условие .Ссылка ЕСТЬ NULL

Прежде чем перейти к методам удаления, давайте выясним, почему прямые проверки на NULL или Неопределено не работают для битых ссылок.

  1. Что такое "Объект не найден"?

    Когда мы видим в поле ссылочного типа значение "Объект не найден", это означает, что объект, на который указывала эта ссылка, был удален из информационной базы. Сама ссылка при этом не обнуляется и не становится Неопределено. Она остается как "фантомная" ссылка, ведущая в никуда, сохраняя при этом свою внутреннюю структуру, но без соответствующего ей объекта в базе.

  2. Почему Поле ЕСТЬ NULL не работает?

    Поле регистра сведений, содержащее такую битую ссылку, само по себе не равно NULL. Оно содержит недействительное, но тем не менее, существующее ссылочное значение. Поэтому попытка отбора или проверки ГДЕ Владелец ЕСТЬ NULL не даст нужного результата.

  3. Почему Поле.Ссылка ЕСТЬ NULL работает?

    Это ключевой момент. Платформа 1С для битых ссылок имеет такую особенность: если попытаться получить внутреннюю ссылку объекта через синтаксис ПолеССылкой.Ссылка, то для *битой* ссылки это выражение вернет именно NULL. Это позволяет нам эффективно отфильтровывать записи с несуществующими объектами в запросах. Если поле является составным типом, содержащим несколько видов ссылок (например, Справочник.Номенклатура, Документ.ПоступлениеТоваров), условие Поле.Ссылка ЕСТЬ NULL все равно будет работать корректно для определения битых ссылок, независимо от конкретного типа объекта, на который указывала битая ссылка.

Программное удаление записей с битыми ссылками

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

Шаг 1: Идентификация битых ссылок запросом

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

Создадим новый запрос и укажем условие Штрихкоды.Владелец.Ссылка ЕСТЬ NULL. Обратите внимание, что мы должны выбрать из запроса все измерения регистра, чтобы потом корректно удалить записи через НаборЗаписей.

Посмотрим на пример кода:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |    Штрихкоды.Владелец КАК Владелец,
    |    Штрихкоды.Штрихкод КАК Штрихкод // Обязательно добавляем все измерения регистра
    |ИЗ
    |    РегистрСведений.Штрихкоды КАК Штрихкоды
    |ГДЕ
    |    Штрихкоды.Владелец.Ссылка ЕСТЬ NULL";

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

В этом запросе мы выбираем не только само поле Владелец, но и Штрихкод, а также любые другие измерения, которые присутствуют в вашем регистре сведений "Штрихкоды". Это критически важно, поскольку при удалении через НаборЗаписей нам потребуется установить отбор по всем измерениям для каждой конкретной записи, которую мы хотим удалить.

Условие Штрихкоды.Владелец.Ссылка ЕСТЬ NULL сработает для всех типов битых ссылок в поле "Владелец", будь то справочник, документ или любой другой ссылочный тип.

Шаг 2: Удаление записей через НаборЗаписей

Получив выборку из запроса, мы можем приступить к пошаговому удалению каждой найденной записи. Для удаления записей регистра сведений используется объект НаборЗаписей. Мы будем итерировать по выборке, для каждой строки создавать новый НаборЗаписей, устанавливать отбор по значениям измерений текущей строки и затем записывать пустой набор.

Проанализируем шаги:

  1. Итерация по выборке: Мы используем цикл Пока Выборка.Следующий Цикл для обхода всех найденных битых записей.
  2. Создание НаборЗаписей: Для каждой записи мы создаем новый экземпляр НаборЗаписей для нашего регистра: НЗ = РегистрыСведений.Штрихкоды.СоздатьНаборЗаписей();.
  3. Установка отбора: Здесь важно понимать, что для удаления конкретной записи необходимо установить отбор по всем измерениям этой записи. Если мы не укажем все измерения, то можем случайно удалить больше записей, чем планировалось. Например, если в нашем регистре есть измерения "Владелец" и "Штрихкод", и мы хотим удалить запись с битым "Владельцем" и конкретным "Штрихкодом", то отбор должен быть установлен по обоим этим измерениям.
    
    НЗ.Отбор.Владелец.Установить(Выборка.Владелец);
    НЗ.Отбор.Штрихкод.Установить(Выборка.Штрихкод); // Добавляем все остальные измерения
    // Если регистр имеет другие измерения, их также нужно добавить в отбор:
    // НЗ.Отбор.ДругоеИзмерение.Установить(Выборка.ДругоеИзмерение);
    

    Это подтверждается тем, что в дискуссии прозвучала важная мысль: "Объектов в базе нет, но ссылки остались и они разные. Поэтому наборы измерений при создании набора записей будут разные." Это означает, что для каждой битой записи нужно формировать свой уникальный отбор.

  4. Запись пустого набора: После установки отбора мы вызываем метод НЗ.Записать(). Когда у НаборЗаписей установлен отбор, и сам набор пуст (то есть мы не считывали в него никаких записей из базы), вызов Записать() приведет к удалению всех записей из регистра, которые соответствуют установленному отбору. Это является стандартным способом удаления записей регистра сведений по отбору.

Вот полный пример кода для удаления:


// Шаг 1: Идентификация битых ссылок запросом
Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |    Штрихкоды.Владелец КАК Владелец,
    |    Штрихкоды.Штрихкод КАК Штрихкод // Обязательно добавляем все измерения регистра
    |ИЗ
    |    РегистрСведений.Штрихкоды КАК Штрихкоды
    |ГДЕ
    |    Штрихкоды.Владелец.Ссылка ЕСТЬ NULL";

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

// Шаг 2: Удаление записей через НаборЗаписей
Пока Выборка.Следующий Цикл
    // Создаем новый набор записей для каждой записи из выборки
    НЗ = РегистрыСведений.Штрихкоды.СоздатьНаборЗаписей();
    
    // Устанавливаем отбор по всем измерениям текущей записи
    // Это гарантирует, что будет удалена только конкретная запись
    НЗ.Отбор.Владелец.Установить(Выборка.Владелец);
    НЗ.Отбор.Штрихкод.Установить(Выборка.Штрихкод); 
    // Если у вас есть другие измерения, добавьте их в отбор:
    // НЗ.Отбор.Измерение3.Установить(Выборка.Измерение3);
    // НЗ.Отбор.Измерение4.Установить(Выборка.Измерение4);
    
    // Запись пустого набора с установленным отбором фактически удаляет записи,
    // соответствующие этому отбору.
    НЗ.Записать(); 
КонецЦикла;

Сообщить("Удаление записей с битыми ссылками завершено.");

Этот код можно поместить в обработку или выполнить в консоли запросов/кода 1С. Перед запуском обязательно сделайте резервную копию базы данных!

Альтернативные методы удаления

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

Метод 1: Использование инструмента "Тестирование и исправление" (ТИС)

Для комплексной проверки и исправления ссылочной целостности базы данных 1С:Предприятие существует встроенный инструмент "Тестирование и исправление" (ТИС). Этот инструмент доступен в режиме "Конфигуратор" через меню "Администрирование".

Рассмотрим шаги использования ТИС:

  1. Создайте резервную копию базы данных. Это самый важный шаг перед любыми операциями с ТИС.
  2. Откройте Конфигуратор. Запустите 1С:Предприятие в режиме "Конфигуратор".
  3. Перейдите в меню "Администрирование" -> "Тестирование и исправление...".
  4. Настройте параметры ТИС:
    • Установите флажок "Поиск и удаление ссылок на несуществующие объекты". Эта опция сканирует все ссылочные поля в базе данных и, обнаружив ссылки, ведущие в никуда, может их очистить или пометить, что приводит к удалению таких записей из регистров, если поле является измерением или реквизитом регистра сведений и выбрано соответствующее действие.
    • Также можно установить флажок "Проверка логической целостности", чтобы выявить другие аномалии в данных.
    • Действие: В качестве действия можно выбрать "Создавать объекты", "Удалять объекты" или "Очищать ссылки". В нашем случае, чтобы удалить записи регистра, содержащие битую ссылку, следует выбрать "Удалять объекты" или "Очищать ссылки" (если поле не является измерением и регистр допускает пустые ссылки). Для регистра сведений, где битая ссылка является частью уникального ключа (измерения), "Удалять объекты" часто является наиболее подходящим.
  5. Нажмите "Выполнить". Дождитесь завершения операции.

Использование ТИС является предпочтительным способом для больших баз данных, так как это штатный инструмент, оптимизированный для работы с СУБД, и не требует программирования. Однако перед его использованием всегда рекомендуется создавать резервную копию базы данных.

Метод 2: Ручное удаление через форму списка регистра сведений

Если количество записей с битыми ссылками не слишком велико, или вы предпочитаете ручной контроль, можно удалить их непосредственно из формы списка регистра сведений.

Разберем процесс:

  1. Откройте регистр сведений "Штрихкоды". Это можно сделать через меню "Все функции" (если доступно пользователю) или найти его в соответствующем разделе интерфейса программы (например, "НСИ и администрирование" -> "Настройки НСИ" -> "Штрихкоды", или через поиск).
  2. Отсортируйте данные по полю "Владелец". Нажмите на заголовок колонки "Владелец" в списке регистра. Это действие сгруппирует все записи, у которых "Владелец" имеет значение "Объект не найден", в начале или конце списка.
  3. Выделите битые записи. Прокрутите список и выделите все строки, у которых в поле "Владелец" отображается "Объект не найден". Вы можете использовать комбинации клавиш Shift+Клик для выделения диапазона или Ctrl+Клик для выборочного выделения.
  4. Удалите выделенные записи. Нажмите клавишу Delete или используйте соответствующую команду в контекстном меню (правая кнопка мыши). Система попросит подтвердить удаление.

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

Важные аспекты и советы

При выполнении любых операций по изменению данных в базе 1С, особенно связанных с массовым удалением, следует придерживаться следующих рекомендаций:

  1. Резервное копирование: Всегда, без исключений, делайте полную резервную копию информационной базы перед выполнением любых операций по удалению или изменению данных. Это ваша "страховка" на случай непредвиденных ошибок.
  2. Тестирование на копии: Если есть возможность, сначала выполните все действия на тестовой копии базы данных. Это позволит убедиться в корректности выбранного метода и отсутствии побочных эффектов, не затронув рабочую базу.
  3. Влияние на производительность: Для очень больших баз данных с миллионами записей программное удаление в цикле может быть долгим. В таких случаях встроенный инструмент "Тестирование и исправление" часто работает более эффективно, так как он оптимизирован для работы с СУБД на низком уровне.
  4. Составные типы: Помните, что подход Поле.Ссылка ЕСТЬ NULL универсален и работает даже для полей составного типа, содержащих множество ссылочных типов.

Мы подробно рассмотрели несколько методов для решения проблемы удаления записей из регистра сведений, где поле с ссылкой имеет значение "Объект не найден". Выбор конкретного метода зависит от объема данных, ваших навыков программирования и доступности инструментария. В большинстве случаев комбинация запроса и удаления через НаборЗаписей является наиболее гибким и эффективным программным решением, а "Тестирование и исправление" – мощным универсальным инструментом.

← На главную