Каждый разработчик 1С рано или поздно сталкивается с удивительной на первый взгляд ситуацией: вы добавляете в справочник совершенно новый реквизит (например, текстовое поле или ссылку на другой объект), выводите его на форму, запускаете обновление конфигурации базы данных и внезапно получаете ошибку: «Код справочника стал неуникальным». Первая реакция вполне естественна — недоумение. Каким образом добавление нового реквизита могло повлиять на уникальность кодов, к которым вы даже не прикасались?
В этой статье мы подробно разберем внутренние механизмы платформы «1С:Предприятие», выясним истинные причины этой ошибки, рассмотрим специфику работы со справочником ХарактеристикиНоменклатуры и составим пошаговый план локализации и устранения проблемы.
Давайте разберем по шагам, что происходит в СУБД (MS SQL Server, PostgreSQL и др.) и на уровне платформы 1С, когда мы вносим изменения в метаданные справочника:
Код (если в свойствах справочника включен параметр «Контроль уникальности»).Таким образом, добавление реквизита не создает дубликаты самостоятельно. Оно лишь заставляет платформу перестроить таблицу СУБД, что поднимает на поверхность ранее накопленные ошибки в данных.
Вы справедливо заметите: «У нас включен контроль уникальности кодов, как дубли вообще могли там оказаться?». Проанализируем основные пути появления неуникальных кодов в обход проверок платформы:
ОбменДанными.Загрузка = Истина. В этом режиме платформа сознательно отключает все проверки бизнес-логики (включая проверку уникальности кодов и номеров документов), чтобы гарантировать беспрепятственную загрузку пакета данных. Это самый частый источник дублей.УстановитьНовыйКод().Стоит обратить внимание на важное замечание опытных разработчиков: в современных типовых решениях 1С (таких как 1С:ERP, Комплексная автоматизация 2, Управление торговлей 11) у справочника ХарактеристикиНоменклатуры длина кода по умолчанию установлена в значение 0. Это означает, что коды в принципе не используются системой для идентификации характеристик — они идентифицируются по владельцу (номенклатуре или виду номенклатуры) и наименованию.
Если вы столкнулись с этой ошибкой именно на справочнике ХарактеристикиНоменклатуры, это сигнализирует об одном из двух факторов:
Для того чтобы успешно применить изменения конфигурации, нам необходимо сначала устранить логические ошибки в данных в режиме «1С:Предприятие». Проанализируем этот процесс по шагам.
Справочник ХарактеристикиНоменклатуры является подчиненным. В зависимости от настроек свойства «Серии кодов» в конфигураторе, уникальность может проверяться либо во всем справочнике (глобально), либо только в пределах владельца (номенклатуры).
Рассмотрим универсальный запрос для поиска дубликатов кодов в разрезе владельцев. Откройте консоль запросов в режиме «1С:Предприятие» и выполните следующий код:
ВЫБРАТЬ
Характеристики.Владелец КАК Владелец,
Характеристики.Код КАК ПовторяющийсяКод,
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Характеристики.Ссылка) КАК КоличествоДублей
ИЗ
Справочник.ХарактеристикиНоменклатуры КАК Характеристики
ГДЕ
Характеристики.Код <> ""
СГРУППИРОВАТЬ ПО
Характеристики.Владелец,
Характеристики.Код
ИМЕЮЩИЕ
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Характеристики.Ссылка) > 1
Если в вашей конфигурации уникальность контролируется глобально по всему справочнику (без учета владельца), используйте более простой вариант запроса:
ВЫБРАТЬ
Характеристики.Код КАК ПовторяющийсяКод,
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Характеристики.Ссылка) КАК КоличествоДублей
ИЗ
Справочник.ХарактеристикиНоменклатуры КАК Характеристики
ГДЕ
Характеристики.Код <> ""
СГРУППИРОВАТЬ ПО
Характеристики.Код
ИМЕЮЩИЕ
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Характеристики.Ссылка) > 1
Выполнив этот запрос, мы получим список всех проблемных кодов, из-за которых СУБД блокирует реструктуризацию таблицы.
После того как проблемные элементы найдены, их коды необходимо сделать уникальными. Разберем три основных способа реализации этой задачи:
Если дубликатов немного (до пары десятков), проще всего открыть эти элементы в режиме «1С:Предприятие» и отредактировать их коды вручную. Для этого можно временно разрешить редактирование кодов в форме элемента (если оно заблокировано стандартным поведением формы) или воспользоваться стандартной обработкой «Групповое изменение реквизитов».
Если дубликатов сотни или тысячи, ручная обработка неэффективна. В этом случае мы можем написать простую обработку, которая автоматически перенумерует проблемные позиции. Рассмотрим пример кода внешней обработки, решающей эту задачу:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Характеристики.Ссылка КАК Ссылка
|ИЗ
| Справочник.ХарактеристикиНоменклатуры КАК Характеристики
|ГДЕ
| Характеристики.Код В
| (ВЫБРАТЬ
| Характер.Код
| ИЗ
| Справочник.ХарактеристикиНоменклатуры КАК Характер
| СГРУППИРОВАТЬ ПО
| Характер.Код
| ИМЕЮЩИЕ
| КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Характер.Ссылка) > 1)";
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
ОбъектХарактеристика = ВыборкаДетальныеЗаписи.Ссылка.ПолучитьОбъект();
// Сбрасываем режим загрузки, чтобы платформа проверила уникальность при записи
ОбъектХарактеристика.ОбменДанными.Загрузка = Ложь;
// Назначаем новый уникальный код автоматически
ОбъектХарактеристика.УстановитьНовыйКод();
Попытка
ОбъектХарактеристика.Записать();
Исключение
Сообщить("Не удалось записать объект: " + ОбъектХарактеристика.Ссылка + " Ошибка: " + ОписаниеОшибки());
КонецПопытки;
КонецЦикла;
В некоторых случаях для исправления логической целостности базы данных помогает штатный механизм администрирования. Запустите Конфигуратор, перейдите в меню Администрирование -> Тестирование и исправление.... Установите флаг «Проверка логической целостности» и выберите вариант «Исправлять ошибки» (предварительно обязательно сделайте резервную копию базы данных!). Платформа попытается автоматически устранить конфликты уникальности.
После того как все дубликаты кодов в режиме «1С:Предприятие» устранены, вернитесь в Конфигуратор и повторно запустите обновление конфигурации базы данных (клавиша F7). Поскольку теперь в таблице нет повторяющихся значений, СУБД без проблем создаст уникальный индекс, процесс реструктуризации успешно завершится, и ваш новый реквизит будет корректно интегрирован в систему.