Вам встретилось сообщение, содержащее строки:
Microsoft OLE DB Provider for SQL Server: CREATE UNIQUE INDEX terminated because a duplicate key was found for index ID
или
Cannot I_nsert duplicate key row in object
или
Попытка вставки неуникального значения в уникальный индекс.
Варианты решения:
1. В SQL Server managment studio физически уничтожаем сбойный индекс (в моем случае это был индекс по таблице итогов регистра бухгалтерии). В 1С распроводим сбойные документы. В режиме тестирования и исправления ставим галки реиндексация таблиц + пересчет итогов. 1С воссоздает индекс уже без ошибки. Проводим ранее сбоившие документы.
2. 1) С помощью Management Studio 2005 сгенерировала create-скрипт на создание индекса, который глючил, и сохранила в файлик.
2) Вручную убила косячный индекс из таблицы _AccumRgTn19455
3) Запустила запрос вида
Код SQL
S_elect count(*), поля_индекса
FROM AccumRgTn19455
GROUP BY поля_индекса
HAVING count(*)>1
После того, как индекс был убит, у меня отобразилось 15 дублирующихся записей, хотя до выполнения п.2 запрос ничего не возвращал.
4) Просмотрела все записи и вручную почистила дубликаты. На самом деле, я ещё пользовалась обработкой «Структура отчёта», чтобы понять, с чем вообще имею дело. Оказалось, что в таблице _AccumRgTn19455 хранится регистр накопления «Выпуск продукции (налоговый учёт)». Я ещё поковырялась sql-запросами, выявила 15 неуникальных документов и после окончания всех действ проверила в 1С, что эти документы проводятся нормально, без ошибок. Просто так чистить таблицы наобум, конечно, не стоит: важно понимать, что чистится и чем это может обернуться.
5) Запустила запрос на создание индекса, который был сохранён в файле.
6) Перевела базу в однопользовательский режим и запустила dbcc checkdb — на этот раз ни одной ошибки не выдалось.
7) Перевела базу обратно в однопользовательский режим.
Всё… проблема побеждена. Ну ещё в 1С запустила «Тестирование и исправление», там тоже всё прошло нормально, перестало ругаться на неуникальный индекс.
3. Если неуникальность заключается в датах с нулевыми значениями, то проблема решается созданием базы с параметром смещения равным 2000.
1. Если проблема загрузкой базы данных, то:
1.1. Если Вы делаете загрузку (используйете dt-файл) в базу MS SQL Server, то при создании базы перед загрузкой укажите смещение дат — 2000.
Если уже база создана со смещением 0, то создайте новую с 2000.
1.2. Если есть возможность в файловом варианте работать с базой, то выполните Тестирование и Исправление, а также Конфигурация — Проверка конфигурации — Проверка логической целостности конфигурации + Поиск некорректных ссылок.
1.3. Если нет файлового варианта, попробуйте загрузить из DT в клиент-серверный вариант с DB2 (который менее требователен к уникальности), и затем выполнить Тестирование и Исправление, а также Конфигурация — Проверка конфигурации — Проверка логической целостности конфигурации + Поиск некорректных ссылок.
1.4. Для локализации проблемы можно определить данные объекта, загрузка которого не удалась. Для этого надо включить во время загрузки трассировку в утилите Profiler или включите запись в технологический журнал событий DBMSSQL и EXCP.
2. Если проблема неуникальности проявляется во время работы пользователей:
2.1. Найти с помощью метода пункта 1.4 проблемный запрос.
2.1.2. Иногда ошибка возникает во время исполнения запросов, например:
Данная ошибка возникает из-за того что в модуле регистра накопления «Рабочее время работников организаций» в процедуре «ЗарегистрироватьПерерасчеты» в запросе не стоит служебное слово «РАЗЛИЧНЫЕ».
Код 1C v 8.х
Т.е. должно быть:
Запрос = Новый Запрос(
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| Основные.ФизЛицо,
. . . . .
В последних выпущенных релизах ЗУП и УПП ошибка не возникает, т.к. там стоит «РАЗЛИЧНЫЕ».
2.2. После нахождения проблемного индекса из предыдущего пункта, необходимо найти неуникальную запись.
2.2.1. «Рыба» скрипта для определения неуникальных записей с помощью SQL:
Код SQL
S_elect 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:
Код SQL
S_elect count(*), _Document140_IDRRef, _KeyField
from _Document140_VT1385
group by _Document140_IDRRef, _KeyField
having count(*) > 1
С его помощью узнайте значения колонок _Document140_IDRRef, _KeyField, дублирующихся записей (id, key).
При помощи запроса:
Код SQL
S_elect *
from _Document140_VT1385
where _Document140_IDRRef = id1 and _KeyField = key1 or _Document140_IDRRef = id2 and _KeyField = key2 or ...
посмотрите на значения других колонок дублирующихся записей.
Если обе записи имеют осмысленные значения и эти значения разные, то исправьте значение _KeyField на уникальное. Для этого определите максимальное занятое значение _KeyField (keymax):
Код SQL
S_elect max(_KeyField)
from _Document140_VT1385
where _Document140_IDRRef = id1
Замените значение _KeyField в одной из повторяющихся записей на правильное:
Код SQL
update _Document140_VT1385
set _KeyField = keymax + 1
where _Document140_IDRRef = id1 and _LineNo1386 = lineno1
Здесь _LineNo1386 = — дополнительное условие, которое позволяет выбрать одну из двух повторяющихся записей.
Если одна (или обе) из повторяющихся записей имеет очевидно неправильное значение, то ее нужно удалить:
Код SQL
delete from _Document140_VT1385
where _Document140_IDRRef = id1 and _LineNo1386 = lineno1
Если повторяющиеся записи имеют одинаковые значения во всех колонках, то из них нужно оставить одну:
Код SQL
S_elect distinct *
into #tmp1
from _Document140_VT1385
where _Document140_IDRRef = id1 and _KeyField = key1
delete from _Document140_VT1385
where _Document140_IDRRef = id1 and _KeyField = key1
I_nsert into _Document140_VT1385
S_elect #tmp1
D_rop table #tmp1
Описанную процедуру необходимо выполнить для каждой пары повторяющихся записей.
2.2.3. Второй пример:
Код SQL
S_elect COUNT(*) AS Expr2, _IDRRef AS Expr1, _Description
FROM _Reference8_
GROUP BY _IDRRef, _Description
HAVING (COUNT(*) > 1)
2.3.4 Пример определения неуникальных записей с помощью запроса 1С:Предприятие:
Код 1C v 8.х
ВЫБРАТЬ Справочник.Ссылка
ИЗ Справочник.Справочник КАК Справочник
СГРУППИРОВАТЬ ПО Справочник.Ссылка
ИМЕЮЩИЕ КОЛИЧЕСТВО(*) > 1
О чем статья
В этой статье будет описано, что делать, если при работе с 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_IDRRef = id1 and _KeyField = key1 or _Document140_IDRRef = id2 and _KeyField = key2 or …
посмотрите на значения других колонок дублирующихся записей.
Если обе записи имеют осмысленные значения и эти значения разные, то исправьте значение _KeyField на уникальное. Для этого определите максимальное занятое значение _KeyField (keymax):
select max(_KeyField)
from _Document140_VT1385
where _Document140_IDRRef = id1
Замените значение _KeyField в одной из повторяющихся записей на правильное:
update _Document140_VT1385
set _KeyField = keymax + 1
where _Document140_IDRRef = id1 and _LineNo1386 = lineno1
Здесь _LineNo1386 = — дополнительное условие, которое позволяет выбрать одну из двух повторяющихся записей.
Если одна (или обе) из повторяющихся записей имеет очевидно неправильное значение, то ее нужно удалить:
delete from _Document140_VT1385
where _Document140_IDRRef = id1 and _LineNo1386 = lineno1
Если повторяющиеся записи имеют одинаковые значения во всех колонках, то из них нужно оставить одну:
select distinct *
into #tmp1
from _Document140_VT1385
where _Document140_IDRRef = id1 and _KeyField = key1
delete from _Document140_VT1385
where _Document140_IDRRef = id1 and _KeyField = key1
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
В этом случаи перед загрузкой выключить использование итогов, загрузить сообщение, включить использование итогов и пересчитать.
Вам встретилось сообщение, содержащее строки:
Microsoft OLE DB Provider for SQL Server: CREATE UNIQUE INDEX terminated because a duplicate key was found for index ID
или
Cannot I_nsert duplicate key row in object
или
Попытка вставки неуникального значения в уникальный индекс.
Варианты решения:
1. В SQL Server managment studio физически уничтожаем сбойный индекс (в моем случае это был индекс по таблице итогов регистра бухгалтерии). В 1С распроводим сбойные документы. В режиме тестирования и исправления ставим галки реиндексация таблиц + пересчет итогов. 1С воссоздает индекс уже без ошибки. Проводим ранее сбоившие документы.
2. 1) С помощью Management Studio 2005 сгенерировала create-скрипт на создание индекса, который глючил, и сохранила в файлик.
2) Вручную убила косячный индекс из таблицы _AccumRgTn19455
3) Запустила запрос вида
Код SQL
S_elect count(*), поля_индекса
FR OM AccumRgTn19455
GROUP BY поля_индекса
HAVING count(*)>1
После того, как индекс был убит, у меня отобразилось 15 дублирующихся записей, хотя до выполнения п.2 запрос ничего не возвращал.
4) Просмотрела все записи и вручную почистила дубликаты. На самом деле, я ещё пользовалась обработкой «Структура отчёта», чтобы понять, с чем вообще имею дело. Оказалось, что в таблице _AccumRgTn19455 хранится регистр накопления «Выпуск продукции (налоговый учёт)». Я ещё поковырялась sql-запросами, выявила 15 неуникальных документов и после окончания всех действ проверила в 1С, что эти документы проводятся нормально, без ошибок. Просто так чистить таблицы наобум, конечно, не стоит: важно понимать, что чистится и чем это может обернуться.
5) Запустила запрос на создание индекса, который был сохранён в файле.
6) Перевела базу в однопользовательский режим и запустила dbcc checkdb — на этот раз ни одной ошибки не выдалось.
7) Перевела базу обратно в однопользовательский режим.
Всё… проблема побеждена. Ну ещё в 1С запустила «Тестирование и исправление», там тоже всё прошло нормально, перестало ругаться на неуникальный индекс.
3. Если неуникальность заключается в датах с нулевыми значениями, то проблема решается созданием базы с параметром смещения равным 2000.
1. Если проблема загрузкой базы данных, то:
1.1. Если Вы делаете загрузку (используйете dt-файл) в базу MS SQL Server, то при создании базы перед загрузкой укажите смещение дат — 2000.
Если уже база создана со смещением 0, то создайте новую с 2000.
1.2. Если есть возможность в файловом варианте работать с базой, то выполните Тестирование и Исправление, а также Конфигурация — Проверка конфигурации — Проверка логической целостности конфигурации + Поиск некорректных ссылок.
1.3. Если нет файлового варианта, попробуйте загрузить из DT в клиент-серверный вариант с DB2 (который менее требователен к уникальности), и затем выполнить Тестирование и Исправление, а также Конфигурация — Проверка конфигурации — Проверка логической целостности конфигурации + Поиск некорректных ссылок.
1.4. Для локализации проблемы можно определить данные объекта, загрузка которого не удалась. Для этого надо включить во время загрузки трассировку в утилите Profiler или включите запись в технологический журнал событий DBMSSQL и EXCP.
2. Если проблема неуникальности проявляется во время работы пользователей:
2.1. Найти с помощью метода пункта 1.4 проблемный запрос.
2.1.2. Иногда ошибка возникает во время исполнения запросов, например:
Данная ошибка возникает из-за того что в модуле регистра накопления «Рабочее время работников организаций» в процедуре «ЗарегистрироватьПерерасчеты» в запросе не стоит служебное слово «РАЗЛИЧНЫЕ».
Код 1C v 8.х
Т.е. должно быть:
Запрос = Новый Запрос(
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| Основные.ФизЛицо,
. . . . .
В последних выпущенных релизах ЗУП и УПП ошибка не возникает, т.к. там стоит «РАЗЛИЧНЫЕ».
2.2. После нахождения проблемного индекса из предыдущего пункта, необходимо найти неуникальную запись.
2.2.1. «Рыба» скрипта для определения неуникальных записей с помощью SQL:
Код SQL
S_elect COUNT(*) Counter, <перечисление всех полей соответствующего индекса> fr om <имя таблицы>
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:
Код SQL
S_elect count(*), _Document140_IDRRef, _KeyField
fr om _Document140_VT1385
group by _Document140_IDRRef, _KeyField
having count(*) > 1
С его помощью узнайте значения колонок _Document140_IDRRef, _KeyField, дублирующихся записей (id, key).
При помощи запроса:
Код SQL
S_elect *
fr om _Document140_VT1385
where _Document140_IDRRef = id1 and _KeyField = key1 or _Document140_IDRRef = id2 and _KeyField = key2 or ...
посмотрите на значения других колонок дублирующихся записей.
Если обе записи имеют осмысленные значения и эти значения разные, то исправьте значение _KeyField на уникальное. Для этого определите максимальное занятое значение _KeyField (keymax):
Код SQL
S_elect max(_KeyField)
fr om _Document140_VT1385
wh ere _Document140_IDRRef = id1
Замените значение _KeyField в одной из повторяющихся записей на правильное:
Код SQL
upd ate _Document140_VT1385
set _KeyField = keymax + 1
wh ere _Document140_IDRRef = id1 and _LineNo1386 = lineno1
Здесь _LineNo1386 = — дополнительное условие, которое позволяет выбрать одну из двух повторяющихся записей.
Если одна (или обе) из повторяющихся записей имеет очевидно неправильное значение, то ее нужно удалить:
Код SQL
delete from _Document140_VT1385
wh ere _Document140_IDRRef = id1 and _LineNo1386 = lineno1
Если повторяющиеся записи имеют одинаковые значения во всех колонках, то из них нужно оставить одну:
Код SQL
S_elect distinct *
into #tmp1
from _Document140_VT1385
wh ere _Document140_IDRRef = id1 and _KeyField = key1
delete from _Document140_VT1385
wh ere _Document140_IDRRef = id1 and _KeyField = key1
I_nsert into _Document140_VT1385
S_elect #tmp1
D_rop table #tmp1
Описанную процедуру необходимо выполнить для каждой пары повторяющихся записей.
2.2.3. Второй пример:
Код SQL
S_elect COUNT(*) AS Expr2, _IDRRef AS Expr1, _Description
FROM _Reference8_
GROUP BY _IDRRef, _Description
HAVING (COUNT(*) > 1)
2.3.4 Пример определения неуникальных записей с помощью запроса 1С:Предприятие:
Код 1C v 8.х
ВЫБРАТЬ Справочник.Ссылка
ИЗ Справочник.Справочник КАК Справочник
СГРУППИРОВАТЬ ПО Справочник.Ссылка
ИМЕЮЩИЕ КОЛИЧЕСТВО(*) > 1
Информация взята с сайта http://helpf.pro
Добрый день!
Занимаюсь разработкой конфигураций на основе платформы 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], из за чего и не происходила реструктуризация таблицы. Кто и как умудрился удалить эти индексы история умалчивает, данный факт восстановлению не подлежит.
Вылечилась данная ситуация следующим запросом:
USE [DB]
GO
CREATE TABLE #TempRecorder (_RecorderRRef BINARY(16))
GO
INSERT INTO #TempRecorder
SELECT T.[_RecorderRRef]
FROM (SELECT COUNT(*) as _count , T1.[_Period] ,T1.[_RecorderRRef] ,T1.[_LineNo]
FROM [dbo].[_AccRg2024] AS T1
GROUP BY T1.[_Period] ,T1.[_RecorderRRef] ,T1.[_LineNo]
HAVING count(*) > 1 ) AS T
--WHERE T.[_RecorderRRef] = 0xBA80000C29053BCD11E2FF4303EA5AA7
GROUP BY T.[_RecorderRRef]
DECLARE @_Count numeric(10), @_Period datetime, @_RecorderRRef binary(16), @_LineNo numeric(9,0);
DECLARE @i int;
SET @i = 0;
DECLARE _Recorder_Cursor CURSOR FOR
SELECT * FROM #TempRecorder;
OPEN _Recorder_Cursor
FETCH NEXT FROM _Recorder_Cursor INTO @_RecorderRRef;
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE _Cursor CURSOR FOR
SELECT [_Period], [_LineNo] FROM [dbo].[_AccRg2024]
WHERE [_RecorderRRef] = @_RecorderRRef
OPEN _Cursor
SET @i=0;
FETCH NEXT FROM _Cursor INTO @_Period, @_LineNo
WHILE @@FETCH_STATUS = 0
BEGIN
SET @i = @i + 1
UPDATE [dbo].[_AccRg2024] SET [_LineNo] = @i
WHERE CURRENT OF _Cursor
FETCH NEXT FROM _Cursor INTO @_Period, @_LineNo
END;
CLOSE _Cursor;
DEALLOCATE _Cursor;
FETCH NEXT FROM _Recorder_Cursor INTO @_RecorderRRef;
END
CLOSE _Recorder_Cursor;
DEALLOCATE _Recorder_Cursor;
GO
DROP TABLE #TempRecorder
GO
Изначально определяются неуникальные записи, выбираются регистраторы и в цикле происходит пере нумерация строк.
После этого, уже средствами 1С, выполнилось тестирование базы с режимом «Реструктуризация таблиц информационной базы», данная процедура пересоздала индексы в таблице, и дальнейшие манипуляции, при работе с метаданными конфигурации, стали происходить без каких либо ошибок.
Получение информации о структуре хранения базы данных в терминах 1С:Предприятие и СУБД
Размещение данных 1С:Предприятия 8. Таблицы и поля
1CDBStorageStructureInfo v2.1
Платформа 8.3 → Битый dt-шник
Ошибка при загрузке dt файловой базы в PostgreSQL:
Ошибка загрузки информационной базы. В информационную базу загружены не все данные
по причине:
Нарушено условие уникальности данных.
Сообщение при загрузке в 1с:
Попытка вставки неуникального значения в уникальный индекс:
ERROR: could not create unique index «_reference643_bydatakey_rr»
DETAIL: Key (_idrref, _nodetref, _noderref)=(x8e02283452a573354532b8d7a08ab2ae, x00000009, x9d04902b34af533b11e2c757fa890d98) is duplicated.
В логе PostgreSQL смотрим:
< 2020-04-09 10:32:08.514 MSK >ERROR: could not create unique index «_reference643_bydatakey_rr»
< 2020-04-09 10:32:08.514 MSK >DETAIL: Key (_idrref, _nodetref, _noderref)=(x8e02283452a573354532b8d7a08ab2ae, x00000009, x9d04902b34af533b11e2c757fa890d98) is duplicated.
< 2020-04-09 10:32:08.514 MSK >STATEMENT: create unique index _reference643_bydatakey_rr on _referencechngr643(_IDRRef, _NodeTRef, _NodeRRef); alter table _referencechngr643 cluster on _reference643_bydatakey_rr;
< 2020-04-09 10:32:08.515 MSK >WARNING: there is no transaction in progress
Мы наши таблицу с которой связана ошибка — _referencechngr643
Простейший вариант очистить таблицу, если повезет (немного данных) может помочь
postgres=# c demo
demo=# SELECT * FROM _referencechngr643;
Картинка (обрезок).
Ошибка при загрузке dt файловой базы в PostgreSQL:
Ошибка загрузки информационной базы. В информационную базу загружены не все данные
по причине:
Нарушено условие уникальности данных.
Сообщение при загрузке в 1с:
Попытка вставки неуникального значения в уникальный индекс:
ERROR: could not create unique index «_reference643_bydatakey_rr»
DETAIL: Key (_idrref, _nodetref, _noderref)=(x8e02283452a573354532b8d7a08ab2ae, x00000009, x9d04902b34af533b11e2c757fa890d98) is duplicated.
В логе PostgreSQL смотрим:
< 2020-04-09 10:32:08.514 MSK >ERROR: could not create unique index «_reference643_bydatakey_rr»
< 2020-04-09 10:32:08.514 MSK >DETAIL: Key (_idrref, _nodetref, _noderref)=(x8e02283452a573354532b8d7a08ab2ae, x00000009, x9d04902b34af533b11e2c757fa890d98) is duplicated.
< 2020-04-09 10:32:08.514 MSK >STATEMENT: create unique index _reference643_bydatakey_rr on _referencechngr643(_IDRRef, _NodeTRef, _NodeRRef); alter table _referencechngr643 cluster on _reference643_bydatakey_rr;
< 2020-04-09 10:32:08.515 MSK >WARNING: there is no transaction in progress
Мы наши таблицу с которой связана ошибка — _referencechngr643
Простейший вариант очистить таблицу, если повезет (немного данных) может помочь
postgres=# c demo
demo=# SELECT * FROM _referencechngr643;
Картинка (обрезок).
demo=# TRUNCATE _referencechngr643;
Если не повезло, нужно смотреть обработкой 1CDBStorageStructureInfo v2.1
что за объект
Справочник.ВидыОпераций.Изменения
После очистки Справочник.ВидыОпераций.Изменения
можно попробовать выгрузить, загрузить Справочник.ВидыОпераций через xml
В данном случае это не поможет, потому что справочник Справочник.ВидыОпераций.Изменения не выгружается через xml.
2. Будем решать вопрос средствами PostgreSQL
Итак наша ошибка:
Попытка вставки неуникального значения в уникальный индекс:
ERROR: could not create unique index «_reference643_bydatakey_rr»
DETAIL: Key (_idrref, _nodetref, _noderref)=(x8e02283452a573354532b8d7a08ab2ae, x00000009, x9d04902b34af533b11e2c757fa890d98) is duplicated.
Создадим запрос для таблицы _referencechngr643
выводящий повторяющиеся записи:
Как найти повторяющиеся записи в PostgreSQL
select
_nodetref,
_noderref,
_idrref, count(*) from
_referencechngr643 group by
_nodetref,
_noderref,
_idrref HAVING count(*) > 1;
Справочник.ВидыОпераций.Изменения
После очистки Справочник.ВидыОпераций.Изменения
можно попробовать выгрузить, загрузить Справочник.ВидыОпераций через xml
В данном случае это не поможет, потому что справочник Справочник.ВидыОпераций.Изменения не выгружается через xml.
2. Будем решать вопрос средствами PostgreSQL
Итак наша ошибка:
Попытка вставки неуникального значения в уникальный индекс:
ERROR: could not create unique index «_reference643_bydatakey_rr»
DETAIL: Key (_idrref, _nodetref, _noderref)=(x8e02283452a573354532b8d7a08ab2ae, x00000009, x9d04902b34af533b11e2c757fa890d98) is duplicated.
Создадим запрос для таблицы _referencechngr643
выводящий повторяющиеся записи:
Как найти повторяющиеся записи в PostgreSQL
select
_nodetref,
_noderref,
_idrref, count(*) from
_referencechngr643 group by
_nodetref,
_noderref,
_idrref HAVING count(*) > 1;
x00000009 | x9d04902b34af533b11e2c757fa890d98 | x90a27b112207742446ec93ee478ec1d1 | 2
x00000009 | x9d04902b34af533b11e2c757fa890d98 | x8e02283452a573354532b8d7a08ab2ae | 2
x00000009 | x9d04902b34af533b11e2c757fa890d98 | xa69d3ff7873e291d48644a507a39f06b | 2
x00000009 | x9d04902b34af533b11e2c757fa890d98 | x9a8b53541966765449d0031809109897 | 2
x00000009 | x9d04902b34af533b11e2c757fa890d98 | xbd6f371cc86afff24983dc095af41b21 | 2
Пример обращения по конкретному условию
where _noderref=E'\x9d04902b34af533b11e2c757fa890d98'
Introduction to inserting PostgreSQL records with Unicode characters
demo=# select _nodetref, _noderref, _idrref
from _referencechngr643 where _noderref=E'\x9d04902b34af533b11e2c757fa890d98';
Однако запросом удалить дубликаты записей мы не сможем, из за отсутствия первичного
ключа. (Будут удалены все записи)
Удалим повторяющиеся записи выгрузив таблицу в файл, отредактировав, а потом
загрузить обратно.
Выгрузим таблицу в файл
demo=# COPY _referencechngr643 TO '/tmp/file.csv' CSV;
COPY 565
Сделаем копию.
demo=# COPY _referencechngr643 TO '/tmp/file-cop.csv' CSV;
COPY 565
В файле мы должны найти и удалить все задвоенные записи, например
x90a27b112207742446ec93ee478ec1d1
Однако запросом удалить дубликаты записей мы не сможем, из за отсутствия первичного
ключа. (Будут удалены все записи)
Удалим повторяющиеся записи выгрузив таблицу в файл, отредактировав, а потом
загрузить обратно.
Выгрузим таблицу в файл
demo=# COPY _referencechngr643 TO '/tmp/file.csv' CSV;
COPY 565
Сделаем копию.
demo=# COPY _referencechngr643 TO '/tmp/file-cop.csv' CSV;
COPY 565
В файле мы должны найти и удалить все задвоенные записи, например
x90a27b112207742446ec93ee478ec1d1
Сохранить файл.
Очистить таблицу
demo=# TRUNCATE _referencechngr643;
Загрузим таблицу из файла
demo=# COPY _referencechngr643 FROM '/tmp/file.csv' CSV;
COPY 560
demo=# REINDEX TABLE _referencechngr643;
REINDEX
Проверка:
demo=# COPY _referencechngr643 TO '/tmp/file-ver.csv' CSV;
COPY 565
Поскольку при загрузке dt реиндексация не прошла до конца:
postgres@u1804$ reindexdb demo