次の表があります。
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
は主キー列です。
私は1日を通して定期的に実行される挿入を実行しています(ストアドプロシージャで):
insert into DataValue(DateStamp, ItemId, Value)
select DateStamp, ItemId, Value from tmp_holding_DataValue;
これにより、保持テーブル(tmp_holding_DataValue
)メインデータテーブル(DataValue
)に渡ります。その後、保持テーブルは切り捨てられます。
問題は、例のように、保持テーブルにメインテーブルにすでに存在するアイテムが含まれている可能性があることです。キーは重複値を許可しないため、手順は失敗します。
1つのオプションは、挿入プロシージャにwhere句を配置することですが、メインデータテーブルには1,000万行以上あり、これには長い時間がかかる可能性があります。
挿入しようとするときに重複をスキップ/無視するだけの手順を取得する他の方法はありますか?
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);
重複キーを無視=はいとしてPKを割り当てることができます。次に、重複キーを無視して警告を表示して続行します。私は推測していません。これをテストしました。
私が見つけたのは、これが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
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
私は同じ重複キーエラーをスローすることになった同様の要件に遭遇しました、そしてアイデアは他の列も返す一方で、異なる(プライマリ)複数の列を選択することでした check :
INSERT INTO DataValue(DateStamp, ItemId, Value)
SELECT DISTINCT DateStamp, ItemId, MAX(Value) AS Value
FROM tmp_holding_DataValue
GROUP BY DateStamp, ItemId
実際、集計関数MAXは単一の値を選択するため、Distinctなしでも目標を達成できます。