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

DateStampItemIdは主キー列です。

私は(ストアドプロシージャで)1日を通して定期的に実行される挿入を行っています:

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

これにより、保持テーブル ( tmp_holding_DataValue) からメイン データ テーブル ( DataValue) にデータが移動します。次に、保持テーブルが切り捨てられます。

問題は、例のように、メイン テーブルに既に存在する項目が保持テーブルに含まれる可能性があることです。キーは重複する値を許可しないため、手順は失敗します。

1 つのオプションは、insert プロシージャに 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ではないということです。スクリプトを使用してインデックスを削除して再作成する必要があります。ただし、インデックスを右クリックして [削除して再作成] を選択し、[重複キーを無視] = [はい] に変更するだけです。私にとって、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 に答える