Подтвердить что ты не робот

Пропустить/игнорировать повторяющиеся строки вставить

У меня есть следующие таблицы:

DataValue

DateStamp    ItemId   Value
----------   ------   -----
2012-05-22   1        6541
2012-05-22   2        12321
2012-05-21   3        32

tmp_holding_DataValue

DateStamp    ItemId   Value
----------   ------   -----
2012-05-22   1        6541
2012-05-22   4        87
2012-05-21   5        234

DateStamp и ItemId являются столбцами первичного ключа.

Я делаю вставку, которая периодически запускается в течение дня (в хранимой процедуре):

insert into DataValue(DateStamp, ItemId, Value)
select DateStamp, ItemId, Value from tmp_holding_DataValue;

Это перемещает данные из таблицы удержания (tmp_holding_DataValue) в таблицу основных данных (DataValue). Стол удерживания затем усекается.

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

Один из вариантов заключается в том, чтобы поместить предложение where в вставку proc, но в таблице основных данных есть 10 миллионов + строк, и это может занять много времени.

Есть ли другой способ заставить процедуру просто пропускать/игнорировать дубликаты при попытке вставить?

4b9b3361

Ответ 1

INSERT dbo.DataValue(DateStamp, ItemId, Value)
SELECT DateStamp, ItemId, Value 
FROM dbo.tmp_holding_DataValue AS t
WHERE NOT EXISTS (SELECT 1 FROM dbo.DataValue AS d
WHERE DateStamp = t.DateStamp
AND ItemId = t.ItemId);

Ответ 2

В SQL Server 2008+:

MERGE
INTO    dataValue dv
USING   tmp_holding_DataValue t
ON      t.dateStamp = dv.dateStamp
        AND t.itemId = dv.itemId
WHEN NOT MATCHED THEN
INSERT  (dateStamp, itemId, value)
VALUES  (dateStamp, itemId, value)
/*
WHEN MATCHED THEN
UPDATE
        value = t.value
*/
-- Uncomment above to rewrite duplicates rather than ignore them

Ответ 3

Вы можете назначить PK как Ignore Duplicate Key = Yes. Затем он будет просто игнорировать дубликат ключа и продолжать. Я не догадываюсь. Я проверил это.

Я обнаружил, что я не могу это сделать, это SMSS. Необходимо сбросить и воссоздать индекс с помощью script. Но вы можете щелкнуть правой кнопкой мыши по индексу, выбрать drop and rereate, а затем просто изменить Ignore Duplicate Key = Yes. Для меня SMSS не сразу показывал изменения.

IF  EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[PKallowDup]') AND name = N'PK_PKallowDup')
ALTER TABLE [dbo].[PKallowDup] DROP CONSTRAINT [PK_PKallowDup]
GO

USE [test]
GO

/****** Object:  Index [PK_PKallowDup]    Script Date: 05/22/2012 10:23:13 ******/
ALTER TABLE [dbo].[PKallowDup] ADD  CONSTRAINT [PK_PKallowDup] PRIMARY KEY CLUSTERED 
(
    [PK] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = ON, IGNORE_DUP_KEY = ON, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO

Или я думаю, вы могли бы использовать внешнее соединение

INSERT dbo.DataValue(DateStamp, ItemId, Value)
SELECT t.DateStamp, t.ItemId, t.Value 
  FROM dbo.tmp_holding_DataValue AS t 
  left join dbo.DataValue AS d
    on d.DateStamp = t.DateStamp
   AND d.ItemId = t.ItemId
 WHERE d.DateStamp is null 
   and d.ItemId    in null

Ответ 4

Я столкнулся с аналогичным требованием, которое в итоге выставило ту же самую повторяющуюся ключевую ошибку, а затем идея заключалась в том, чтобы выбрать несколько столбцов, которые являются отличными (Primary), возвращая также другие столбцы, проверьте:

INSERT INTO DataValue(DateStamp, ItemId, Value)
SELECT DISTINCT DateStamp, ItemId, MAX(Value) AS Value
FROM tmp_holding_DataValue
GROUP BY DateStamp, ItemId

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