Почему при добавлении реквизита в 1С возникает ошибка «Код справочника стал неуникальным» и как ее исправить?

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

Каждый разработчик 1С рано или поздно сталкивается с удивительной на первый взгляд ситуацией: вы добавляете в справочник совершенно новый реквизит (например, текстовое поле или ссылку на другой объект), выводите его на форму, запускаете обновление конфигурации базы данных и внезапно получаете ошибку: «Код справочника стал неуникальным». Первая реакция вполне естественна — недоумение. Каким образом добавление нового реквизита могло повлиять на уникальность кодов, к которым вы даже не прикасались?

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

Техническая причина: как реструктуризация таблиц СУБД вытаскивает «скелеты из шкафа»

Давайте разберем по шагам, что происходит в СУБД (MS SQL Server, PostgreSQL и др.) и на уровне платформы 1С, когда мы вносим изменения в метаданные справочника:

  1. Обычный режим работы: Когда пользователи работают в системе, создают новые элементы или записывают существующие, платформа контролирует уникальность кодов «на лету» в момент транзакции записи конкретного объекта. Если в базе уже есть скрытые дубликаты, платформа не сканирует всю таблицу при каждом открытии или записи других элементов. Дубликаты могут спокойно «спать» в базе данных годами.
  2. Добавление реквизита и запуск реструктуризации: Как только мы добавляем новый реквизит, структура таблицы физически меняется. Платформа 1С инициирует процесс реструктуризации таблицы СУБД. На уровне базы данных это выглядит так: создается временная таблица с новой структурой, в нее копируются все существующие данные из старой таблицы, старая таблица удаляется, а временная переименовывается в основную.
  3. Наложение индексов и ограничений: После переноса данных платформа обязана заново построить системные индексы, включая уникальный индекс по полю Код (если в свойствах справочника включен параметр «Контроль уникальности»).
  4. Сбой транзакции: В процессе построения уникального индекса СУБД натыкается на записи с одинаковыми кодами. СУБД физически не может создать уникальный индекс по неуникальным данным и возвращает ошибку. Конфигуратор прерывает обновление и сообщает пользователю, что код стал неуникальным.

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

Откуда в базе данных вообще берутся дубликаты кодов?

Вы справедливо заметите: «У нас включен контроль уникальности кодов, как дубли вообще могли там оказаться?». Проанализируем основные пути появления неуникальных кодов в обход проверок платформы:

Особенность справочника «ХарактеристикиНоменклатуры»

Стоит обратить внимание на важное замечание опытных разработчиков: в современных типовых решениях 1С (таких как 1С:ERP, Комплексная автоматизация 2, Управление торговлей 11) у справочника ХарактеристикиНоменклатуры длина кода по умолчанию установлена в значение 0. Это означает, что коды в принципе не используются системой для идентификации характеристик — они идентифицируются по владельцу (номенклатуре или виду номенклатуры) и наименованию.

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

  1. Вы работаете в старой или сильно кастомизированной конфигурации (например, УПП 1.3 или УТ 10.3), где код у этого справочника еще существовал.
  2. Кто-то из предыдущих разработчиков вручную включил использование кода и контроль уникальности для данного справочника в свойствах конфигурации.

Пошаговое руководство по исправлению ошибки

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

Шаг 1. Локализация дубликатов запросом

Справочник ХарактеристикиНоменклатуры является подчиненным. В зависимости от настроек свойства «Серии кодов» в конфигураторе, уникальность может проверяться либо во всем справочнике (глобально), либо только в пределах владельца (номенклатуры).

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


ВЫБРАТЬ
    Характеристики.Владелец КАК Владелец,
    Характеристики.Код КАК ПовторяющийсяКод,
    КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Характеристики.Ссылка) КАК КоличествоДублей
ИЗ
    Справочник.ХарактеристикиНоменклатуры КАК Характеристики
ГДЕ
    Характеристики.Код <> ""
СГРУППИРОВАТЬ ПО
    Характеристики.Владелец,
    Характеристики.Код
ИМЕЮЩИЕ
    КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Характеристики.Ссылка) > 1

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


ВЫБРАТЬ
    Характеристики.Код КАК ПовторяющийсяКод,
    КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Характеристики.Ссылка) КАК КоличествоДублей
ИЗ
    Справочник.ХарактеристикиНоменклатуры КАК Характеристики
ГДЕ
    Характеристики.Код <> ""
СГРУППИРОВАТЬ ПО
    Характеристики.Код
ИМЕЮЩИЕ
    КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Характеристики.Ссылка) > 1

Выполнив этот запрос, мы получим список всех проблемных кодов, из-за которых СУБД блокирует реструктуризацию таблицы.

Шаг 2. Исправление дубликатов кодов

После того как проблемные элементы найдены, их коды необходимо сделать уникальными. Разберем три основных способа реализации этой задачи:

Способ А. Ручное изменение кодов

Если дубликатов немного (до пары десятков), проще всего открыть эти элементы в режиме «1С:Предприятие» и отредактировать их коды вручную. Для этого можно временно разрешить редактирование кодов в форме элемента (если оно заблокировано стандартным поведением формы) или воспользоваться стандартной обработкой «Групповое изменение реквизитов».

Способ Б. Программная перенумерация

Если дубликатов сотни или тысячи, ручная обработка неэффективна. В этом случае мы можем написать простую обработку, которая автоматически перенумерует проблемные позиции. Рассмотрим пример кода внешней обработки, решающей эту задачу:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Характеристики.Ссылка КАК Ссылка
    |ИЗ
    |	Справочник.ХарактеристикиНоменклатуры КАК Характеристики
    |ГДЕ
    |	Характеристики.Код В
    |		(ВЫБРАТЬ
    |			Характер.Код
    |		ИЗ
    |			Справочник.ХарактеристикиНоменклатуры КАК Характер
    |		СГРУППИРОВАТЬ ПО
    |			Характер.Код
    |		ИМЕЮЩИЕ
    |			КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Характер.Ссылка) > 1)";

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

Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
    ОбъектХарактеристика = ВыборкаДетальныеЗаписи.Ссылка.ПолучитьОбъект();
    // Сбрасываем режим загрузки, чтобы платформа проверила уникальность при записи
    ОбъектХарактеристика.ОбменДанными.Загрузка = Ложь;
    // Назначаем новый уникальный код автоматически
    ОбъектХарактеристика.УстановитьНовыйКод();
    Попытка
        ОбъектХарактеристика.Записать();
    Исключение
        Сообщить("Не удалось записать объект: " + ОбъектХарактеристика.Ссылка + " Ошибка: " + ОписаниеОшибки());
    КонецПопытки;
КонецЦикла;

Способ В. Использование Тестирования и Исправления (ТиИ)

В некоторых случаях для исправления логической целостности базы данных помогает штатный механизм администрирования. Запустите Конфигуратор, перейдите в меню Администрирование -> Тестирование и исправление.... Установите флаг «Проверка логической целостности» и выберите вариант «Исправлять ошибки» (предварительно обязательно сделайте резервную копию базы данных!). Платформа попытается автоматически устранить конфликты уникальности.

Завершение обновления базы данных

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

← На главную