Как исправить ошибку «Набор записей, принадлежащий менеджеру записи должен содержать ровно 1 запись»

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

В процессе работы с высоконагруженными системами на базе 1С, такими как ERP Управление предприятием или Комплексная автоматизация, программисты часто сталкиваются со специфической системной ошибкой: «Набор записей, принадлежащий менеджеру записи должен содержать ровно 1 запись». Данная ситуация является критической, так как она блокирует работу кадровых документов, проведение настроек или открытие важных форм. Разберем подробно, почему возникает этот сбой и как его устранить различными методами.

Причина возникновения проблемы

Для начала проанализируем архитектуру регистров сведений. В 1С существуют регистры, которые не имеют ни одного измерения — в них присутствуют только ресурсы и реквизиты. С точки зрения логики платформы, такой регистр может содержать только одну строку. Для обращения к этой строке используется объект РегистрСведенийМенеджерЗаписи.

Ошибка возникает в тот момент, когда из-за программного сбоя, некорректного обмена данными или прямого вмешательства в базу данных на уровне СУБД в таком регистре физически появляется две и более записи. Платформа «теряется»: менеджер записи пытается прочитать «единственную» строку, находит несколько и выдает исключение, так как не может определить, какую из них считать актуальной. Обычное Тестирование и исправление (ТИИ) зачастую не видит в этом ошибки, так как индексы уникальности в таких таблицах могут отсутствовать или работать иначе.

Шаг 1. Поиск проблемного регистра

Если в тексте ошибки не указано имя регистра (например, она возникает при открытии формы документа), нам необходимо его вычислить. Рассмотрим основные способы:

  1. Замер производительности: включим замер в конфигураторе перед выполнением действия и остановим сразу после появления окна ошибки. Последняя строка кода в стеке вызовов укажет на обращение к конкретному регистру.
  2. Технологический журнал: проанализируем логи на предмет событий EXCP. Там будет зафиксирован SQL-запрос, в котором фигурирует имя таблицы (например, _InfoReg1234).
  3. Типовые места: в ERP наиболее часто эта проблема встречается в регистрах НастройкиУчетаВремени, ПараметрыРаботыПрограммы или служебных регистрах настроек пользователей.

Шаг 2. Программное решение через Набор Записей

Простое удаление через менеджер записи (СоздатьМенеджерЗаписи().Удалить()) не сработает, так как менеджер сам по себе инициирует проверку на количество записей. Выясним, как обойти это ограничение. Рассмотрим самый эффективный метод — использование объекта НаборЗаписей с принудительным режимом загрузки.

Выполним следующий код во внешней обработке:


// Выбираем нужный регистр
НЗ = РегистрыСведений.НастройкиУчетаВремени.СоздатьНаборЗаписей();

// Устанавливаем режим загрузки, который отключает стандартные проверки платформы
НЗ.ОбменДанными.Загрузка = Истина;

// Записываем пустой набор, чтобы полностью очистить регистр
НЗ.Записать();

Установка свойства ОбменДанными.Загрузка = Истина является ключевым моментом. Это сообщает платформе, что данные записываются «как есть», без выполнения прикладных проверок и логики подписок на события, которые могли бы вызвать повторное появление ошибки.

Шаг 3. Универсальный скрипт для исправления всех регистров

Если мы подозреваем, что проблема носит массовый характер или хотим создать инструмент для профилактики, проанализируем ситуацию программно по всем метаданным. Посмотрим на пример кода, который находит регистры без измерений, проверяет их на наличие «дублей» и схлопывает лишние записи:


Для Каждого Рег Из Метаданные.РегистрыСведений Цикл
    // Проверяем только регистры без измерений
    Если Рег.Измерения.Количество() = 0 Тогда
        НаборЗаписей = РегистрыСведений[Рег.Имя].СоздатьНаборЗаписей();
        НаборЗаписей.Прочитать();
        
        // Если записей больше одной — это наша ошибка
        Если НаборЗаписей.Количество() > 1 Тогда
            Сообщить("Обнаружены дубли в регистре: " + Рег.Имя);
            
            // Выгружаем записи в таблицу значений для сворачивания
            ТЗ = НаборЗаписей.Выгрузить();
            
            // Формируем список колонок для свертки (все ресурсы и реквизиты)
            КолонкиСвертки = "";
            Для Каждого Колонка Из ТЗ.Колонки Цикл
                КолонкиСвертки = КолонкиСвертки + Колонка.Имя + ",";
            КонецЦикла;
            КолонкиСвертки = Лев(КолонкиСвертки, СтрДлина(КолонкиСвертки) - 1);
            
            // Сворачиваем таблицу, оставляя только уникальную строку
            ТЗ.Свернуть(КолонкиСвертки);
            
            // Загружаем обратно и записываем в режиме обмена
            НаборЗаписей.Загрузить(ТЗ);
            НаборЗаписей.ОбменДанными.Загрузка = Истина;
            НаборЗаписей.Записать(Истина);
            
            Сообщить("Регистр " + Рег.Имя + " успешно очищен от дублей.");
        КонецЕсли;
    КонецЕсли;
КонецЦикла;

Шаг 4. Решение для клиент-серверного варианта (SQL)

В исключительных случаях, когда программные методы 1С не помогают (что случается крайне редко при использовании ОбменДанными.Загрузка), задачу можно решить на уровне СУБД. Разберем этот алгоритм:

  1. Определим имя таблицы в SQL через функцию ПолучитьСтруктуруХраненияБазыДанных().
  2. Зайдем в консоль SQL Server Management Studio.
  3. Выполним команду полной очистки таблицы: TRUNCATE TABLE _InfoRegXXXX (где XXXX — номер таблицы вашего регистра).

Важно: после очистки таблицы через SQL необходимо перезапустить сеанс 1С или очистить кэш, чтобы платформа увидела изменения. Помните, что TRUNCATE полностью удаляет данные, поэтому после этого настройки в программе (например, константы учета времени) нужно будет пересохранить вручную.

Рекомендации по профилактике

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

Правильный подход при записи в такие регистры:

← На главную