Одной из самых неприятных проблем, с которой может столкнуться администратор или разработчик 1С при обновлении конфигурации или активном перепроведении документов, является ошибка СУБД: «Попытка вставки неуникального значения в уникальный индекс». Эта ситуация блокирует работу с регистром и не позволяет системе корректно рассчитывать остатки и обороты. Проанализируем причины возникновения этой коллизии и разберем по шагам, как её устранить, сохранив целостность данных.
Для начала разберем природу ошибки. Платформа 1С:Предприятие при работе с SQL-сервером (MS SQL Server, PostgreSQL) создает физические таблицы для хранения итогов. Чтобы обеспечить высокую скорость выборки данных, на эти таблицы накладываются уникальные индексы. Обычно уникальность определяется комбинацией полей: Период + Счет + Субконто + Разделитель.
Рассмотрим ситуацию, описанную в теме: система сообщает о повторяющемся значении ключа, где дата указана как 4018-09-01. Не стоит пугаться «даты из будущего». Проанализируем механизм хранения дат в 1С: при создании базы данных часто устанавливается смещение дат 2000 лет. Это означает, что дата 4018 год в SQL соответствует привычному 2018 году в интерфейсе 1С. Таким образом, коллизия возникла в данных за сентябрь 2018 года.
Почему же файловая версия базы данных может «проглатывать» эту ошибку, а SQL-версия — нет? Выясним причину: механизмы индексации в файловой базе .1cd менее строгие к физическим дублям в таблицах итогов. При загрузке данных из файла .dt в SQL, платформа пытается заново построить уникальные индексы «с нуля». Если в данных закралась логическая ошибка или произошел сбой транзакции, SQL-сервер обнаруживает две абсолютно идентичные строки и блокирует создание индекса, что приводит к аварийному завершению процесса.
Самый безопасный и эффективный способ «забороть» проблему без прямого вмешательства в структуру базы данных средствами SQL — это использование встроенных механизмов платформы. Рассмотрим алгоритм действий:
Когда мы отключаем использование итогов для конкретного регистра, платформа выполняет команду TRUNCATE TABLE для соответствующих таблиц итогов в SQL. Это полностью очищает таблицу, удаляя все записи, включая проблемные дубли. Затем, при обратном включении и пересчете, 1С заново формирует итоги на основании записей регистра (движений), которые обычно не имеют проблем с уникальностью.
Выполним следующий код во внешней обработке:
// Отключаем использование итогов для регистра бухгалтерии
РегистрыБухгалтерии.Хозрасчетный.УстановитьИспользованиеИтогов(Ложь);
// Включаем использование итогов обратно
РегистрыБухгалтерии.Хозрасчетный.УстановитьИспользованиеИтогов(Истина);
// Запускаем полный пересчет итогов
РегистрыБухгалтерии.Хозрасчетный.ПересчитатьИтоги();
Важно: Этот процесс может занять значительное время, если база данных имеет большой объем. Однако это гарантирует, что структура индексов будет пересоздана корректно.
Если простой пересчет не помогает, нам необходимо выяснить, какие именно объекты вызывают конфликт. В сообщении об ошибке обычно фигурируют бинарные данные (GUID), например: 0xa40c02215ef0a00011e8b5d8222db703. Это уникальные идентификаторы ссылочных объектов (счетов, субконто, подразделений).
Посмотрим на пример того, как можно найти виновника в интерфейсе 1С. Для этого нам нужно преобразовать HEX-строку из ошибки в стандартный формат УникальныйИдентификатор. Проанализируем последовательность действий:
ПолучитьСсылку() для поиска объекта в базе.
// Пример поиска счета по GUID из ошибки
ИдентификаторТекст = "a40c0221-5ef0-a000-11e8-b5d8222db703"; // Пример преобразованного GUID
Ид = Новый УникальныйИдентификатор(ИдентификаторТекст);
СсылкаНаСчет = ПланыСчетов.Хозрасчетный.ПолучитьСсылку(Ид);
Если СсылкаНаСчет.Пустая() Тогда
Сообщить("Объект не найден");
Иначе
Сообщить("Проблемный объект: " + СсылкаНаСчет);
КонецЕсли;
Найдя «косячные» документы или элементы справочников, мы можем попробовать их перепровести. Часто это помогает системе корректно обновить записи в таблицах итогов.
Разберем стандартный функционал платформы для борьбы с подобными ошибками. В конфигураторе перейдем в меню «Администрирование» — «Тестирование и исправление». Нам важны следующие флаги:
Рассмотрим нюанс: в клиент-серверном варианте реиндексация через ТиИ заставляет SQL Server выполнить команду REINDEX. Это очищает фрагментацию и иногда позволяет устранить мелкие сбои в структуре страниц данных.
Если мы хотим увидеть «врага в лицо» до того, как предпринимать радикальные меры, воспользуемся консолью SQL Server Management Studio (SSMS). Нам нужно найти записи, которые группируются более одного раза по ключевым полям индекса.
Проанализируем пример запроса для поиска дублей (название таблицы итогов можно узнать через ПолучитьСтруктуруХраненияБазыДанных()):
SELECT Period, AccountID, Splitter, COUNT(*)
FROM _AccTotals2 -- Имя таблицы вашего регистра
GROUP BY Period, AccountID, Splitter
HAVING COUNT(*) > 1
Если запрос вернул строки, значит, в базе действительно физически присутствуют дубли. В этом случае наиболее правильным решением будет именно Метод 1 (отключение и включение итогов через 1С), так как платформа сама корректно очистит таблицу _AccTotals, не нарушая связей между метаданными.
Подведем итог: ошибка «неуникального значения в уникальном индексе» — это чаще всего следствие сбоя в таблицах итогов, а не в самих движениях документов.
Краткий план спасения базы:
УстановитьИспользованиеИтогов(Ложь) и затем обратно Истина. Это самый быстрый и «чистый» способ..dt, выполните ТиИ в файловом варианте, а затем попробуйте загрузить в SQL снова.Помните, что прямое удаление строк из таблиц SQL через DELETE крайне не рекомендуется, так как это может привести к расхождению остатков в отчетах. Всегда отдавайте предпочтение штатным методам платформы 1С.