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
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
Vous devez vous connecter pour publier un commentaire.
Vous êtes absent le
WHERE
dans votreUPDATE
déclaration donc, actuellement, il va essayer et mettre à jour toutes les lignes de la table avec les mêmes valeurs.Il arrive même aux meilleurs d'entre nous. Comment saurais-je que, vous demandez-vous? 🙂
OriginalL'auteur Martin Smith