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