La Violation de la contrainte de CLÉ UNIQUE sur INSÉRER OÙ COUNT(*) = 0 sur SQL Server 2005

Je suis pour l'insertion dans une base de données SQL à partir de plusieurs processus. Il est probable que le processus sera parfois essayer d'insérer des données en double dans la table. J'ai essayé d'écrire la requête d'une manière qui va gérer les doublons mais j'ai toujours:

System.Data.SqlClient.SqlException: Violation of UNIQUE KEY constraint 'UK1_MyTable'. Cannot insert duplicate key in object 'dbo.MyTable'.
The statement has been terminated.

Ma requête ressemble à quelque chose comme:

INSERT INTO MyTable (FieldA, FieldB, FieldC)
SELECT FieldA='AValue', FieldB='BValue', FieldC='CValue'
WHERE (SELECT COUNT(*) FROM MyTable WHERE FieldA='AValue' AND FieldB='BValue' AND FieldC='CValue' ) = 0

La contrainte " UK1_MyConstraint dit que dans MyTable, la combinaison des 3 champs doit être unique.

Mes questions:

  1. Pourquoi ne pas ce travail?
  2. Quelle modification dois-je faire si il n'y a pas de chance de faire une exception en raison de la violation de la contrainte?

Remarque que je suis au courant qu'il existe d'autres approches pour résoudre le problème initial de la "INSERTION si n'existe pas" comme (en résumé):

  • À l'aide de TRY CATCH
  • S'il n'EXISTE PAS INSÉRER (à l'intérieur d'une transaction sérialisable isolement)

Dois-je utiliser l'une des approches?

Edit 1 SQL de Création de Table:

CREATE TABLE [dbo].[MyTable](
  [Id] [bigint] IDENTITY(1,1) NOT NULL,
  [FieldA] [bigint] NOT NULL,
  [FieldB] [int] NOT NULL,
  [FieldC] [char](3) NULL,
  [FieldD] [float] NULL,
  CONSTRAINT [PK_MyTable] PRIMARY KEY NONCLUSTERED 
  (
    [Id] ASC
  )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON),
  CONSTRAINT [UK1_MyTable] UNIQUE NONCLUSTERED 
  (
    [FieldA] ASC,
    [FieldB] ASC,
    [FieldC] ASC
  )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON)
)

Edit 2 Décision:

Juste de mettre à jour ce - que j'ai décidé d'utiliser le "JFDI" la mise en œuvre suggérée dans la question (lien). Même si je suis toujours curieux de savoir pourquoi la mise en œuvre d'origine ne fonctionne pas.

  • Connexes: stackoverflow.com/questions/3407857/...
  • Je n'ai rien d'utile à ajouter, mais votre réputation actuelle (1234) est la même que la combinaison de mes bagages.
  • J'espère que vous allez garder vos bagages, la combinaison de la synchronisation que ma réputation changements. Vous pourriez avoir besoin pour obtenir une nouvelle serrure si ma réputation n'est jamais à 5 chiffres 🙂
  • Je pense que @Mike Cheel l'a, ou, au moins, a identifié une condition qui peut provoquer cela. Si BValue ou CValue sont nulles, votre SELECT COUNT(*) renvoie 0, à moins que ANSI_NULLS est ÉTEINT.
  • Je suis toujours à l'aide de WHERE NOT EXISTS, et il fonctionne très bien pour moi. Je pense aussi que le problème pourrait être d'accepter les valeurs null dans les champs.
  • Juste pour être clair, je ne suis pas d'insérer les valeurs null (mais cela ne veut pas dire que d'autres personnes pourraient avoir ce problème à cause de l'insertion de valeurs null avec ANSI_NULLS être sur).
  • Rien dans votre approche actuelle est la prévention de ces erreurs. En vertu de suffisamment de charge élevée, vous verrez.
  • Smith: intéressant. Me semble que je n'ai pas pensé à cette même assez bien. Je suppose que je devrais revoir ces lieux et ajouter le TRY-CATCH comme dans le "JFDI" version...
  • Connexes: stackoverflow.com/questions/639854/...

InformationsquelleAutor Iain | 2010-09-24