La Violation de la contrainte de CLÉ UNIQUE au cours de SQL de mise à jour

J'ai une simple table de base de données (SQL Server 2008 R2 Express), qui a une définition comme suit:

ID         INT          Auto Inc, PK
Name       VARCHAR(64)  Unique Key
Telephone  VARCHAR(128)

J'ai une procédure stockée qui j'execute pour mettre à jour des enregistrements dans la table qui fait la suivante:

UPDATE customers
SET    Name = @name, Telephone = @Telephone
WHERE  id = @id

Actuellement, j'ai deux entrées dans la table

ID   Name    Telephone
1    Fred    01234 567890
2    John    09876 543210

Lorsque j'appelle une procédure stockée pour mettre à jour le numéro de téléphone de Jean, le SQL, qui est effectivement exécutée est

UPDATE customers
SET    Name = 'John', Telephone = '02468 135790'
WHERE  id = 2

Cela génère une CLÉ UNIQUE de la violation sur les Name champ. Maintenant que le Nom de domaine n'a pas vraiment changer, pourquoi cela se produit-il?

Que toutes les actions de base de données sont traitées par mon application à l'aide de procédures stockées, j'ai pu résoudre ce problème en supprimant la contrainte, et en modifiant les procédures stockées manuellement appliquer la contrainte, mais cela semble juste mauvais.

Étant donné que mon tableau en réalité a beaucoup plus de champs, il doit y avoir un générique de travail autour de ce que je peux employer pour éviter ces faux contrainte de problèmes, sans avoir à générer de nombreuses procédures stockées pour mettre à jour des champs spécifiques?

Modifier: Le tableau ci-dessus a été simplifié pour garder la question plus faciles à gérer, je suis sûr que je n'ai pas oublié quelque chose d'important, mais pour info, la définition réelle de la table est comme suit

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[companies](
[id] [int] IDENTITY(1,1) NOT NULL,
[typeId] [int] NOT NULL,
[name] [varchar](64) NOT NULL,
[displayName] [varchar](128) NOT NULL,
[deliveryAddress] [varchar](1024) NOT NULL,
[invoiceAddress] [varchar](1024) NOT NULL,
[telephone] [varchar](64) NOT NULL,
[fax] [varchar](64) NOT NULL,
[email] [varchar](256) NOT NULL,
[website] [varchar](256) NULL,
[isActive] [bit] NOT NULL,
CONSTRAINT [PK_companies] PRIMARY KEY CLUSTERED 
(
[id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY],
CONSTRAINT [Unique Display Name] UNIQUE NONCLUSTERED 
(
[displayName] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY],
CONSTRAINT [Unique Name] UNIQUE NONCLUSTERED 
(
[name] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[companies]  WITH CHECK ADD  CONSTRAINT [Company Type] FOREIGN KEY([id])
REFERENCES [dbo].[companyTypes] ([id])
GO
ALTER TABLE [dbo].[companies] CHECK CONSTRAINT [Company Type]
GO

...et de la procédure stockée

ALTER PROCEDURE UpdateCompany
@id                 INT,
@typeId             INT,
@name               VARCHAR(64),
@displayName        VARCHAR(128),
@deliveryAddress    VARCHAR(1024),
@invoiceAddress     VARCHAR(1024),
@telephone          VARCHAR(64),
@fax                VARCHAR(64),
@email              VARCHAR(256),
@website            VARCHAR(256),
@isActive           BIT
AS
BEGIN
UPDATE  companies
SET     typeid = @typeid,
name = @name,
displayname = @displayname,
deliveryAddress = @deliveryAddress,
invoiceAddress = @invoiceAddress,
telephone = @telephone,
fax = @fax,
email = @email,
website = @website,
isActive = @isActive
EXEC    GetCompany @id
END
GO
Absolument, cela ne semble pas bonne. Êtes-vous positif qu'il n'y a pas vraiment un doublon et que la contrainte unique a été préalablement activé sans le WITH CHECK option qui permettrait de valider les données existantes? Ou avez-vous des déclencheurs qui pourraient en être la cause?
Vous pouvez poster votre code de procédure stockée?
Il vous manque le WHERE dans votre UPDATE déclaration donc, actuellement, il va essayer et mettre à jour toutes les lignes.
Ah! Ne peux pas croire que j'ai raté ça! Le temps de l'appeler une nuit, je pense. Merci de poster une réponse de Martin, et je vais accepter (et souffrir de l'embarras de laisser cette question ouverte pour tout voir).
C'est probablement une bonne chose que vous avez une contrainte unique sur le Nom.. sinon la totalité de la table aurait été arrosé.

OriginalL'auteur Bryan | 2011-08-30