J'ai les tables suivantes:
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
et ItemId
sont les colonnes de clé primaire.
Je fais un insert qui fonctionne périodiquement tout au long de la journée (dans une procédure stockée):
insert into DataValue(DateStamp, ItemId, Value)
select DateStamp, ItemId, Value from tmp_holding_DataValue;
Cela déplace les données de la table de stockage (tmp_holding_DataValue
) dans la table de données principale (DataValue
). La table de maintien est alors tronquée.
Le problème est que, comme dans l'exemple, la table de stockage peut contenir des éléments qui existent déjà dans la table principale. Étant donné que la clé n'autorisera pas les valeurs en double, la procédure échouera.
Une option serait de placer une clause where sur le processus d'insertion, mais la table de données principale contient plus de 10 millions de lignes, ce qui peut prendre beaucoup de temps.
Existe-t-il un autre moyen de faire en sorte que la procédure ignore ou ignore les doublons lors de la tentative d'insertion?
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);
Vous pouvez attribuer à la clé la clé Ignore Duplicate Key = Yes. Ensuite, il va simplement donner une clé de duplication d'avertissement ignoré et continuer. Je ne devine pas. J'ai testé cela.
Ce que j'ai trouvé, c'est que je ne peux pas faire cela, c'est SMSS. Doit supprimer et recréer l'index via un script. Mais vous pouvez faire un clic droit sur l’index, sélectionner déposer et recréer, puis simplement changer Ignore Duplicate Key = Yes. Pour moi, SMSS n'a pas immédiatement montré le changement.
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
Ou je pense que vous pourriez utiliser une jointure externe
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
J'ai rencontré une exigence similaire qui a fini par générer la même erreur de clé en double, puis l'idée était de sélectionner plusieurs colonnes distinctes (Primaire) tout en renvoyant d'autres colonnes, check :
INSERT INTO DataValue(DateStamp, ItemId, Value)
SELECT DISTINCT DateStamp, ItemId, MAX(Value) AS Value
FROM tmp_holding_DataValue
GROUP BY DateStamp, ItemId
En fait, l'objectif pourrait être atteint sans Distinct également puisque la fonction d'agrégat MAX sélectionnera une valeur unique.