29

我有以下表格:

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) 中。然后将保留表截断。

问题在于,与示例中一样,holding table 可能包含主表中已经存在的项目。由于该键不允许重复值,因此该过程将失败。

一种选择是在插入过程中放置​​一个 where 子句,但主数据表有 1000 万多行,这可能需要很长时间。

有没有其他方法可以让程序在尝试插入时跳过/忽略重复项?

4

4 回答 4

30
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);
于 2012-05-22T14:10:57.300 回答
22

您可以将 PK 分配为 Ignore Duplicate Key = Yes。然后它只会给出一个警告重复键被忽略并继续。我不是在猜测。我对此进行了测试。

我发现我不能这样做的是 SMSS。必须通过脚本删除并重新创建索引。但是您可以右键单击索引,选择 drop and recreate,然后只需更改 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
于 2012-05-22T14:39:38.820 回答
17

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 SET
        value = t.value
*/
-- Uncomment above to rewrite duplicates rather than ignore them
于 2012-05-22T14:12:47.723 回答
1

我遇到了一个类似的要求,最终引发了相同的重复键错误,然后我的想法是选择多个不同的列(主),同时返回其他列,检查

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

事实上,目标也可以在没有 Distinct 的情况下实现,因为聚合函数 MAX 将选择单个值。

于 2017-10-31T19:42:09.967 回答