Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Как обойти ошибку попытки вставки не уникального значения в индекс через insert into selec  [new]
leonix
Member

Откуда:
Сообщений: 403
Переношу данные из одной таблицы в другую. Вылетает ошибка о том что пытаюсь вставить не уникальное значение в уникальный индекс. Как это можно обойти. Т.е. добавлять такую строку в этом случае.
Ниже запрос.
insert into [dbo].[_InfoRg222] (
[_Fld223],--объект 
[_Fld224], --номер версии
[_Fld251], --дата версии
[_Fld225], --версия объекта
[_Fld226], --автор версии
[_Fld232], -- контрольная сумма
[_SimpleKey]
) 
SELECT         
[_Fld276],--объект 
[_Fld256]+10000000, --номер версии
[_Fld259], --дата 
[_Fld257],-- версии объекта
[_Fld277], --автор версии
[_Fld264], --контрольная сумма
Convert(binary(16),NEWID()) --[_SimpleKey] --
FROM  _InfoRg254
where [_Fld259]>='4017-08-01 00:00:00.000' and [_Fld259]<'4017-09-01 00:00:00.000'
15 ноя 18, 14:24    [21735213]     Ответить | Цитировать Сообщить модератору
 Re: Как обойти ошибку попытки вставки не уникального значения в индекс через insert into selec  [new]
leonix
Member

Откуда:
Сообщений: 403
leonix
Т.е. добавлять такую строку в этом случае.


Т.е. НЕ добавлять такую строку в этом случае.
15 ноя 18, 14:26    [21735214]     Ответить | Цитировать Сообщить модератору
 Re: Как обойти ошибку попытки вставки не уникального значения в индекс через insert into selec  [new]
Гавриленко Сергей Алексеевич
Member

Откуда: Moscow
Сообщений: 36989
leonix
leonix
Т.е. добавлять такую строку в этом случае.


Т.е. НЕ добавлять такую строку в этом случае.
Вставлять те, где row_number ( partition by <поля, которые вы пихаете в никальный индекс> order by <порядок записей, который нравится> ) равен 1.

Сообщение было отредактировано: 15 ноя 18, 14:28
15 ноя 18, 14:27    [21735217]     Ответить | Цитировать Сообщить модератору
 Re: Как обойти ошибку попытки вставки не уникального значения в индекс через insert into selec  [new]
leonix
Member

Откуда:
Сообщений: 403
Гавриленко Сергей Алексеевич, Спасибо. С ходу не осилил ваш ответ. Пойду изучать.
15 ноя 18, 14:32    [21735231]     Ответить | Цитировать Сообщить модератору
 Re: Как обойти ошибку попытки вставки не уникального значения в индекс через insert into selec  [new]
Glebanski
Member

Откуда: Msk ->NL
Сообщений: 308
leonix,

По "рабоче-крестьянски" вот так

ALTER TABLE dbo.TableTest ADD CONSTRAINT DF_TableTest_SampleKey_DEF DEFAULT Convert(binary(16),NEWID()) FOR _SampleKey;
insert into [dbo].[_InfoRg222] (
[_Fld223],--объект 
[_Fld224], --номер версии
[_Fld251], --дата версии
[_Fld225], --версия объекта
[_Fld226], --автор версии
[_Fld232]
) 
SELECT distinct       
[_Fld276],--объект 
[_Fld256]+10000000, --номер версии
[_Fld259], --дата 
[_Fld257],-- версии объекта
[_Fld277], --автор версии
[_Fld264]
FROM  _InfoRg254;
15 ноя 18, 14:41    [21735242]     Ответить | Цитировать Сообщить модератору
 Re: Как обойти ошибку попытки вставки не уникального значения в индекс через insert into selec  [new]
iap
Member

Откуда: Москва
Сообщений: 46983
Добавить в WHERE - NOT EXISTS(SELECT * FROM ... WHERE <сравнение уникальных полей>)
15 ноя 18, 14:51    [21735264]     Ответить | Цитировать Сообщить модератору
 Re: Как обойти ошибку попытки вставки не уникального значения в индекс через insert into selec  [new]
iap
Member

Откуда: Москва
Сообщений: 46983
iap
Добавить в WHERE - NOT EXISTS(SELECT * FROM ... WHERE <сравнение уникальных полей>)
Нет. Ерунду написал. Неуникальность-то появляется в источнике.
15 ноя 18, 14:52    [21735266]     Ответить | Цитировать Сообщить модератору
 Re: Как обойти ошибку попытки вставки не уникального значения в индекс через insert into selec  [new]
leonix
Member

Откуда:
Сообщений: 403
Всем спасибо! Буду думать. Там ещё одна проблема, в таблице приемнике есть данные и они могут быть не уникальными при заливке.
15 ноя 18, 15:10    [21735299]     Ответить | Цитировать Сообщить модератору
 Re: Как обойти ошибку попытки вставки не уникального значения в индекс через insert into selec  [new]
Glebanski
Member

Откуда: Msk ->NL
Сообщений: 308
leonix,

Ну тогда
MERGE into blah-blahblah
USING (SELECT distinct ... )

У вас токо непонятно, что собсно Primary Key
15 ноя 18, 15:29    [21735329]     Ответить | Цитировать Сообщить модератору
 Re: Как обойти ошибку попытки вставки не уникального значения в индекс через insert into selec  [new]
leonix
Member

Откуда:
Сообщений: 403
Glebanski
leonix,

Ну тогда
MERGE into blah-blahblah
USING (SELECT distinct ... )

У вас токо непонятно, что собсно Primary Key


CREATE UNIQUE CLUSTERED INDEX [_InfoRg222_ByDims_SNT] ON [dbo].[_InfoRg222]
(
	[_Fld223] ASC,
	[_Fld224] ASC,
	[_Fld251] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
15 ноя 18, 15:42    [21735352]     Ответить | Цитировать Сообщить модератору
 Re: Как обойти ошибку попытки вставки не уникального значения в индекс через insert into selec  [new]
DaniilSeryi
Member

Откуда:
Сообщений: 1723
А рассказывать про CHECK CONSTRAINT никто не хочет, так как предполагается,что проблем и ошибок в таблице после его использования будет больше, чем без использования?
15 ноя 18, 15:57    [21735369]     Ответить | Цитировать Сообщить модератору
 Re: Как обойти ошибку попытки вставки не уникального значения в индекс через insert into selec  [new]
TaPaK
Member

Откуда: Kiev
Сообщений: 6801
DaniilSeryi
А рассказывать про CHECK CONSTRAINT никто не хочет, так как предполагается,что проблем и ошибок в таблице после его использования будет больше, чем без использования?

зачем? тогда уже просто drop
15 ноя 18, 15:59    [21735370]     Ответить | Цитировать Сообщить модератору
 Re: Как обойти ошибку попытки вставки не уникального значения в индекс через insert into selec  [new]
DaniilSeryi
Member

Откуда:
Сообщений: 1723
TaPaK
DaniilSeryi
А рассказывать про CHECK CONSTRAINT никто не хочет, так как предполагается,что проблем и ошибок в таблице после его использования будет больше, чем без использования?

зачем? тогда уже просто drop



Вообще, тут сам собой напрашивается Merge - значения нет - кидаем в таблицу-приемник, значение есть - игнорируем.

merge dbo.t as target
using (select id from dbo.t2) as source (i)
on target.id=source.i
when not matched by target --вставит в таблицу-цель все строки из таблице-источника, для которых не нашлось соответствия в таблице-цели
then insert (id)
values (i);


Легко объединяется с идеей насчёт использования Row_Number()

Гавриленко Сергей Алексеевич
leonix
пропущено...

Т.е. НЕ добавлять такую строку в этом случае.
Вставлять те, где row_number ( partition by <поля, которые вы пихаете в никальный индекс> order by <порядок записей, который нравится> ) равен 1.
15 ноя 18, 16:06    [21735374]     Ответить | Цитировать Сообщить модератору
 Re: Как обойти ошибку попытки вставки не уникального значения в индекс через insert into selec  [new]
Glebanski
Member

Откуда: Msk ->NL
Сообщений: 308
Блин, кто так поля называет. Руки бы оторвал. В SAP-e и то понятнее.
15 ноя 18, 16:21    [21735392]     Ответить | Цитировать Сообщить модератору
 Re: Как обойти ошибку попытки вставки не уникального значения в индекс через insert into selec  [new]
TaPaK
Member

Откуда: Kiev
Сообщений: 6801
Glebanski
Блин, кто так поля называет. Руки бы оторвал. В SAP-e и то понятнее.

1С похоже :)
15 ноя 18, 16:22    [21735394]     Ответить | Цитировать Сообщить модератору
 Re: Как обойти ошибку попытки вставки не уникального значения в индекс через insert into selec  [new]
Glebanski
Member

Откуда: Msk ->NL
Сообщений: 308
leonix,

И да, distinct не пользуйте. Row_number лучше. с вашим
 partition by (_Fld223, _Fld224, _Fld251 order by _Fld257 (наверное? ))
15 ноя 18, 16:24    [21735395]     Ответить | Цитировать Сообщить модератору
 Re: Как обойти ошибку попытки вставки не уникального значения в индекс через insert into selec  [new]
Glebanski
Member

Откуда: Msk ->NL
Сообщений: 308
Aargh! опять чушь написал. Если у ТС уже CONSTRAINT существует на исходной таблице, то там значения по любому уникальные уже. Тогда ему у Row_number никакой не нужен и вообще дедупликация. Простой MERGE.
15 ноя 18, 16:27    [21735399]     Ответить | Цитировать Сообщить модератору
 Re: Как обойти ошибку попытки вставки не уникального значения в индекс через insert into selec  [new]
iap
Member

Откуда: Москва
Сообщений: 46983
MERGE сам по себе никакого преимущества по сравнению с INSERT не даёт.
SELECT из источника должен быть без дубликатов уникальных полей - применяем ROW_NUMBER(), выбираем с номером 1.
INSERT должен проверять, нет ли уже в таблице такого же значения уникальных полей, которые поставляет SELECT - применяем WHERE NOT EXISTS().
15 ноя 18, 16:42    [21735414]     Ответить | Цитировать Сообщить модератору
 Re: Как обойти ошибку попытки вставки не уникального значения в индекс через insert into selec  [new]
Glebanski
Member

Откуда: Msk ->NL
Сообщений: 308
iap,

У ТС там уже
UNIQUE CLUSTERED INDEX [_InfoRg222_ByDims_SNT] ON [dbo].[_InfoRg222]
15 ноя 18, 16:53    [21735435]     Ответить | Цитировать Сообщить модератору
 Re: Как обойти ошибку попытки вставки не уникального значения в индекс через insert into selec  [new]
iap
Member

Откуда: Москва
Сообщений: 46983
Glebanski
iap,

У ТС там уже
UNIQUE CLUSTERED INDEX [_InfoRg222_ByDims_SNT] ON [dbo].[_InfoRg222]
Значит, у него не худший вариант. Я рад за него.
15 ноя 18, 16:56    [21735440]     Ответить | Цитировать Сообщить модератору
 Re: Как обойти ошибку попытки вставки не уникального значения в индекс через insert into selec  [new]
Balbidon
Member

Откуда: Donetsk->Emerald City
Сообщений: 345
Для совсем ленивого решения можно пересоздать UNIQUE с указанием:

IGNORE_DUP_KEY = ON



Быстродействие, возможно, будет еще то и структурно использование данного флага мне не нравится, но для разовой операции может и сгодиться.

Впрочем, на Azure SQL Database (ну нету обычного под рукой, извините) быстродействие не отличается:

SET STATISTICS IO ON
SET STATISTICS TIME ON

CREATE TABLE u(ai int)
CREATE TABLE nu(ai int)
GO

CREATE UNIQUE CLUSTERED INDEX idx1 ON u(ai) WITH (IGNORE_DUP_KEY = ON)
CREATE CLUSTERED INDEX idx1 ON nu(ai)
GO

INSERT INTO u select object_id from sys.objects
INSERT INTO nu select object_id from sys.objects
GO

INSERT INTO u select object_id from sys.objects
INSERT INTO nu select object_id from sys.objects
GO


+


SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 7 ms.

SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 7 ms.
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 0 ms.

SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 7 ms.

SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 6 ms.
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 8 ms.
Table 'u'. Scan count 0, logical reads 215, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'sysschobjs'. Scan count 1, logical reads 67, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(107 row(s) affected)


(1 row(s) affected)


SQL Server Execution Times:
CPU time = 16 ms, elapsed time = 9 ms.
Table 'nu'. Scan count 0, logical reads 215, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'sysschobjs'. Scan count 1, logical reads 67, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(107 row(s) affected)


(1 row(s) affected)


SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 10 ms.
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 0 ms.
Table 'u'. Scan count 0, logical reads 214, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'sysschobjs'. Scan count 1, logical reads 67, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(0 row(s) affected)


(1 row(s) affected)


SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 10 ms.
Duplicate key was ignored.
Table 'nu'. Scan count 0, logical reads 214, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'sysschobjs'. Scan count 1, logical reads 67, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(107 row(s) affected)


(1 row(s) affected)


SQL Server Execution Times:
CPU time = 15 ms, elapsed time = 8 ms.
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 0 ms.

SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 0 ms.


И план одинаковый.
16 ноя 18, 00:59    [21735875]     Ответить | Цитировать Сообщить модератору
 Re: Как обойти ошибку попытки вставки не уникального значения в индекс через insert into selec  [new]
leonix
Member

Откуда:
Сообщений: 403
Всем спасибо, вроде перенёс. Теперь другая проблема.
Я же нумерацию испортил, чтобы не было дублей

[_Fld256]+10000000, --номер версии


Теперь нужно восстановить её обратно. Нумерация в рамкам "[_Fld223],--объект" и порядок по полю "[_Fld251], --дата версии".
Т.е. создать нумерацию версий по объекту по хронологии.
Понимаю что через update делать и как то прикрутить
"row_number ( partition by <поля, которые вы пихаете в никальный индекс> order by <порядок записей, который нравится> ) "
Но мало опыта. Подскажите.
16 ноя 18, 16:38    [21736591]     Ответить | Цитировать Сообщить модератору
 Re: Как обойти ошибку попытки вставки не уникального значения в индекс через insert into selec  [new]
uaggster
Member

Откуда:
Сообщений: 827
leonix, новое поле в таблице сделайте, в нем - что хотите - восстановите.
Потом дропните предыдущее, а это новое - переименуйте.

И вообще, если таблица не очень большая, не миллиарды записей - просто пересоздайте таблицу целиком, как вам хочется.
Создайте рядом, перезалейте данные, старую сделайте _old, новую - переименуйте как старую.
С FK только не факапните.
19 ноя 18, 09:05    [21737772]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить