Занимаюсь разработкой конфигураций на основе платформы 1С: Предприятие. При разворачивании копии базы сформированной средствами 1С: Предприятие регулярно появлялась ошибка:

В процессе обновления информационной базы произошла критическая ошибка
по причине:
Попытка вставки неуникального значения в уникальный индекс:
Microsoft SQL Server Native Client 11.0: Выполнение инструкции CREATE UNIQUE INDEX прервано, поскольку обнаружен повторяющийся ключ для объекта с именем «dbo._AccRg2024NG» и индекса с именем "_AccRg2024_ByPeriod_TRNNG". Повторяющееся значение ключа: (сен 30 4013 12:00AM, 0x0000001c, 0x83fd001b78e2ed3011e342e2cb8d7e1c, 1).
HRESULT=80040E2F, SQLSrvr: SQLSTATE=23000, state=1, Severity=10, native=1505, line=1

Так как копии разворачивались только в целях внесения изменений в конфигурацию и тестирования, этой ошибке не предавали особого значения, пока не понадобилось добавить предопределенный счет. При обновлении конфигурации происходила реструктуризация регистра бухгалтерии и вываливалась данная не приглядная ошибка. Дальнейшее обновление прекращалось. Гугление данного вопроса результатов не дало. пришлось разбираться самим.

Выяснение имени таблицы 1С связанной с объектом определяется функцией ПолучитьСтруктуруХраненияБазыДанных, там же можно поглядеть и состав индексов.

Как оказалось данные индексы в таблице SQL "_AccRg2024" отсутствовали физически. При дальнейшем анализе данных уже средствами SQL выяснилось, что не уникальными были номера записей в разрезе Периода — [_Period], регистратора — [_RecorderRRef] и номер записи [_LineNo], из за чего и не происходила реструктуризация таблицы. Кто и как умудрился удалить эти индексы история умалчивает, данный факт восстановлению не подлежит.

Вылечилась данная ситуация следующим запросом:

Изначально определяются неуникальные записи, выбираются регистраторы и в цикле происходит пере нумерация строк.

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

Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.

ОБЛАСТЬ ПРИМЕНЕНИЯ: SQL Server База данных SQL Azure Azure Synapse Analytics (хранилище данных SQL) Parallel Data Warehouse APPLIES TO: SQL Server Azure SQL Database Azure Synapse Analytics (SQL DW) Parallel Data Warehouse

Сведения Details

Название продукта Product NameSQL Server SQL Server
Идентификатор события Event ID1505 1505
Источник события Event SourceMSSQLSERVER MSSQLSERVER
Компонент ComponentSQLEngine SQLEngine
Символическое имя Symbolic NameDUP_KEY DUP_KEY
Текст сообщения Message TextВыполнение инструкции CREATE UNIQUE INDEX прервано, так как обнаружен повторяющийся ключ, относящийся к имени объекта "%.*ls" и имени индекса "%.*ls". CREATE UNIQUE INDEX terminated because a duplicate key was found for object name ‘%.*ls’ and index name ‘%.*ls’. Повторяющимся значением ключа является %ls. The duplicate key value is %ls.

Объяснение Explanation

Эта ошибка происходит при попытке создать уникальный индекс, а указанное повторяющееся значение содержится больше чем в одной строке в таблице. This error occurs when you attempt to create a unique index and more than one row in the table contains the specified duplicate value. Уникальный индекс создается при создании индекса и указании ключевого слова UNIQUE либо при создании ограничения UNIQUE. A unique index is created when you create an index and specify the UNIQUE keyword, or when you create a UNIQUE constraint. Таблица не может содержать какие-либо строки, которые имеют повторяющиеся значения в столбцах, определенных в индексе или ограничении. The table cannot contain any rows that have duplicate values in the columns defined in the index or constraint.

Давайте рассмотрим данные в таблице Employee: Consider the data in the following Employee table:

LastName LastNameFirstName FirstNameНазвание должности JobTitleHireDate HireDate
Уолтерс WaltersРоб RobСтарший конструктор средств Senior Tool Designer2004-11-19 2004-11-19
Коричневый BrownКевин KevinСпециалист по маркетингу Marketing AssistantNULL NULL
Коричневый BrownДжо JoИнженер-проектировщик Design EngineerNULL NULL
Уолтерс WaltersРоб RobКонструктор средств Tool Designer2001-08-09 2001-08-09

Из-за того, что в строках есть повторяющиеся значения, мы не можем создать уникальный индекс по столбцу LastName или сочетанию столбцов LastName, FirstName. A unique index can not be created on the column combinations LastName or LastName, FirstName because of duplicate values in the rows.

Менее очевидно, что в столбце HireDate также может нарушаться уникальность. Less obvious is the potential for a uniqueness violation in the HireDate column. В целях индексирования значения NULL рассматриваются как равные. For indexing purposes, NULL values compare as equal. Следовательно, нельзя создать уникальный индекс или ограничение, если значения ключа NULL присутствуют больше чем в одной строке. Therefore, you cannot create a unique index or constraint if the key values are NULL in more than one row. С учетом вышесказанного мы не можем создать уникальный индекс по столбцу HireDate или сочетанию столбцов LastName, HireDate. Given the data above, a unique index cannot be created on the column combinations HireDate or LastName, HireDate.

В сообщении об ошибке 1505 возвращается первая строка, нарушающая ограничение уникальности. Error message 1505 returns the first row that violates the uniqueness constraint. В таблице могут быть другие повторяющиеся строки. There may be other duplicate rows in the table. Чтобы найти все повторяющиеся строки, выполните запрос к указанной таблице и используйте предложения GROUP BY и HAVING, чтобы получить информацию о повторяющихся строках. To find all duplicate rows, query the specified table and use the GROUP BY and HAVING clauses to report the duplicate rows. Например, следующий запрос возвращает строки таблицы Employee, в которых есть повторяющиеся значения имени и фамилии: For example, the following query returns the rows in the Employee table that have duplicate first and last names.

SELECT LastName, FirstName, count(*) FROM dbo.Employee GROUP BY LastName, FirstName HAVING count(*) > 1; SELECT LastName, FirstName, count(*) FROM dbo.Employee GROUP BY LastName, FirstName HAVING count(*) > 1;

Действие пользователя User Action

Рассмотрим следующие решения. Consider the following solutions.

Добавить или удалить столбцы в определении индекса или ограничения, чтобы создать уникальное сочетание. Add or remove columns in the index or constraint definition to create a unique composite. В предыдущем примере мы можем решить проблему повторения значений, добавив в определение индекса или ограничения столбец MiddleName. In the previous example, adding a MiddleName column to the index or constraint definition might resolve the duplication problem.

Выбирайте столбцы, определенные как NOT NULL, при определении столбцов для уникального индекса или ограничения уникальности. Select columns that are defined as NOT NULL when you choose columns for a unique index or constraint. При этом исключается возможность возникновения нарушения уникальности, когда больше чем в одной строке содержится значение NULL в значениях ключа. This eliminates the possibility of a uniqueness violation caused when more than one row contains NULL in the key values.

Если дублирование значений является результатом ошибок ввода данных, исправьте данные вручную и затем создайте индекс или ограничение. If the duplicate values are the result of data entry errors, manually correct the data and then create the index or constraint. Дополнительные сведения об удалении повторяющихся строк в таблице см. в статье 139444 базы знаний Майкрософт: Удаление повторяющихся строк из таблицы в SQL Server. For information about removing duplicate rows in a table, see Knowledge Base article 139444: How to remove duplicate rows from a table in SQL Server.

О чем статья

В этой статье будет описано, что делать, если при работе с 1С:Предприятие 8.1 Вам встретилось сообщение, содержащее строки:

Cannot insert duplicate key row in object

Попытка вставки неуникального значения в уникальный индекс.

Что такое индекс?

Подобно содержанию в книге, индекс в базе данных позволяет быстро искать конкретные сведения в таблице.

Индексы представляют собой структуру, позволяющую выполнять ускоренный доступ к строкам таблицы на основе значений одного или более ее столбцов.
Индекс содержит ключи, построенные из одного или нескольких столбцов таблицы или представления, и указатели, которые сопоставляются с местом хранения заданных данных.
Индексы сокращают объем данных, которые необходимо считать, чтобы возвратить результирующий набор.

Хотя индекс и связан с конкретным столбцом (или столбцами) таблицы, все же он является самостоятельным объектом базы данных.

Индексы таблиц в базе данных 1С:Предприятие создаются неявным образом при создании объектов конфигурации, а также при тех или иных настройках объектов конфигурации.

Физическая сущность индексов в MS SQL Server 2005.

Физически данные хранятся на 8Кб страницах. Сразу после создания, пока таблица не имеет индексов, таблица выглядит как куча (heap) данных. Записи не имеют определенного порядка хранения.
Когда вы хотите получить доступ к данным, SQL Server будет производить сканирование таблицы (table scan). SQL Server сканирует всю таблицу, что бы найти искомые записи.
Отсюда становятся понятными базовые функции индексов:
— увеличение скорости доступа к данным,
— поддержка уникальности данных.

Несмотря на достоинства, индексы так же имеют и ряд недостатков. Первый из них – индексы занимают дополнительное место на диске и в оперативной памяти. Каждый раз когда вы создаете индекс, вы сохраняете ключи в порядке убывания или возрастания, которые могут иметь многоуровневую структуру. И чем больше/длиннее ключ, тем больше размер индекса. Второй недостаток – замедляются операции вставки, обновления и удаления записей.
В среде MS SQL Server 2005 реализовано несколько типов индексов:

  • некластерные индексы;
  • кластерные (или кластеризованные) индексы;
  • уникальные индексы;
  • индексы с включенными столбцами
  • индексированные представления
  • полнотекстовый
  • XML

Уникальный индекс

Уникальность значений в индексируемом столбце гарантируют уникальные индексы. При их наличии сервер не разрешит вставить новое или изменить существующее значение таким образом, чтобы в результате этой операции в столбце появились два одинаковых значения.
Уникальный индекс является своеобразной надстройкой и может быть реализован как для кластерного, так и для некластерного индекса. В одной таблице может существовать один уникальный кластерный и множество уникальных некластерных индексов.
Уникальные индексы следует определять только тогда, когда это действительно необходимо. Для обеспечения целостности данных в столбце можно определить ограничение целостности UNIQUE или PRIMARY KEY, а не прибегать к уникальным индексам. Их использование только для обеспечения целостности данных является неоправданной тратой пространства в базе данных. Кроме того, на их поддержание тратится и процессорное время.

1С:Предприятие 8.1 начиная с версии 8.1 активно использует кластерные уникальные индексы. Это означает, что при конвертации с 8.0 или переходе с 8.1.7 можно получить ошибку неуникального индекса.

Если неуникальность заключается в датах с нулевыми значениями, то проблема решается созданием базы с параметром смещения равным 2000.

Что делать?

1. Если проблема загрузкой базы данных, то:

1.1. Если Вы делаете загрузку (используйете dt-файл) в базу MS SQL Server, то при создании базы перед загрузкой укажите смещение дат — 2000.

Если уже база создана со смещением 0, то создайте новую с 2000.

1.2. Если есть возможность в файловом варианте работать с базой, то выполните Тестирование и Исправление, а также Конфигурация — Проверка конфигурации — Проверка логической целостности конфигурации + Поиск некорректных ссылок.

1.3. Если нет файлового варианта, попробуйте загрузить из DT в клиент-серверный вариант с DB2 (который менее требователен к уникальности), и затем выполнить Тестирование и Исправление, а также Конфигурация — Проверка конфигурации — Проверка логической целостности конфигурации + Поиск некорректных ссылок.

1.4. Для локализации проблемы можно определить данные объекта, загрузка которого не удалась. Для этого надо включить во время загрузки трассировку в утилите Profiler или включите запись втехнологический журнал событий DBMSSQL и EXCP.

1.5. Если доступна узел (планы обменов), то выполнить обмен. Можно также дополнительно перед обменом выполнить пункт 2.3.5

2. Если проблема неуникальности проявляется во время работы пользователей:

2.1. Найти с помощью метода пункта 1.4 проблемный запрос.

2.1.2. Иногда ошибка возникает во время исполнения запросов, например:

Данная ошибка возникает из-за того что в модуле регистра накопления «Рабочее время работников организаций» в процедуре «ЗарегистрироватьПерерасчеты» в запросе не стоит служебное слово «РАЗЛИЧНЫЕ».

Запрос = Новый Запрос(
«ВЫБРАТЬ РАЗЛИЧНЫЕ
| Основные.ФизЛицо,

В последних выпущенных релизах ЗУП и УПП ошибка не возникает, т.к. там стоит «РАЗЛИЧНЫЕ».

2.2. После нахождения проблемного индекса из предыдущего пункта, необходимо найти неуникальную запись.

2.2.1. «Рыба» скрипта для определения неуникальных записей с помощью SQL:
SELECT COUNT(*) Counter, from
GROUP BY
HAVING Counter > 1

2.2.2 Пример. Индекс в ошибке называется «_Document140_VT1385_IntKeyIndNG».

Перечень полей таблицы:

_Document140_IDRRef, _KeyField, _LineNo1386, _Fld1387, _Fld1388, _Fld1389, _Fld1390, _Fld1391RRef, _Fld1392RRef, _Fld1393_TYPE, _Fld1393_RTRef, _Fld1393_RRRef, _Fld1394,

_Fld1395, _Fld1396RRef, _Fld1397, _Fld1398, _Fld1399RRef, _Fld22260_TYPE, _Fld22260_RTRef, _Fld22260_RRRef, _Fld22261_TYPE, _Fld22261_RTRef, _Fld22261_RRRef

Перед выполнением приведенной ниже процедуры сделайте резервную копию базы данных.
Выполните в MS SQL Server Query Analizer:

select count(*), _Document140_IDRRef, _KeyField
from _Document140_VT1385
group by _Document140_IDRRef, _KeyField
having count(*) > 1

С его помощью узнайте значения колонок _Document140_IDRRef, _KeyField, дублирующихся записей (id, key).

При помощи запроса:

select *
from _Document140_VT1385
where _Document140_ >

посмотрите на значения других колонок дублирующихся записей.

Если обе записи имеют осмысленные значения и эти значения разные, то исправьте значение _KeyField на уникальное. Для этого определите максимальное занятое значение _KeyField (keymax):

select max(_KeyField)
from _Document140_VT1385
where _Document140_ >

Замените значение _KeyField в одной из повторяющихся записей на правильное:

update _Document140_VT1385
set _KeyField = keymax + 1
where _Document140_ >

Здесь _LineNo1386 = — дополнительное условие, которое позволяет выбрать одну из двух повторяющихся записей.

Если одна (или обе) из повторяющихся записей имеет очевидно неправильное значение, то ее нужно удалить:

delete from _Document140_VT1385
where _Document140_ >

Если повторяющиеся записи имеют одинаковые значения во всех колонках, то из них нужно оставить одну:

select distinct *
into #tmp1
from _Document140_VT1385
where _Document140_ >

delete from _Document140_VT1385
where _Document140_ >

insert into _Document140_VT1385
select #tmp1

drop table #tmp1

Описанную процедуру необходимо выполнить для каждой пары повторяющихся записей.

2.2.3. Второй пример:

SELECT COUNT(*) AS Expr2, _IDRRef AS Expr1, _Description
FROM _Reference8_
GROUP BY _IDRRef, _Description
HAVING (COUNT(*) > 1)

2.3.4 Пример определения неуникальных записей с помощью запроса 1С:Предприятие:

ВЫБРАТЬ Справочник.Ссылка
ИЗ Справочник.Справочник КАК Справочник
СГРУППИРОВАТЬ ПО Справочник.Ссылка
ИМЕЮЩИЕ КОЛИЧЕСТВО(*) > 1

или для бухгалтерии

ВЫБРАТЬ
Подзапрос.Период,
Подзапрос.Регистратор,
,
СУММА(Подзапрос.КоличествоЗаписей) КАК КоличествоЗаписей
ИЗ
(ВЫБРАТЬ
Хозрасчетный.Период КАК Период,
Хозрасчетный.Регистратор КАК Регистратор,
,
1 КАК КоличествоЗаписей
ИЗ
РегистрБухгалтерии.Хозрасчетный КАК Хозрасчетный) КАК Подзапрос

СГРУППИРОВАТЬ ПО
Подзапрос.Период,
Подзапрос.Регистратор,

ИМЕЮЩИЕ
СУММА(Подзапрос.КоличествоЗаписей) > 1

2.3.5 Сделать индекс субд не уникальным. Заксриптовать индекс с помощью Management Studio.

Далее удалить текущий индекс, скорректировать текст и создать скриптом неуникальный индекс.

2.3.6 Частный случай при обмене в РБД. Ошибка приходится на «вспомогательные» таблицы, связанные с расчетом итогов или аналитики. Например:

Ошибка при вызове метода контекста (Записать): Попытка вставки неуникального значения в уникальный индекс:
Microsoft OLE DB Provider for SQL Server: Cannot insert duplicate key row in object ‘dbo._AccntRegED10319’ with unique index ‘_Accnt10319_ByPeriod_TRNRN’.
HRESULT=80040E2F, SQLSrvr: Error state=1, Severity=E, native=2601, line=1

В этом случаи перед загрузкой выключить использование итогов, загрузить сообщение, включить использование итогов и пересчитать.