【发布时间】:2011-08-30 20:51:20
【问题描述】:
我有一个简单的数据库表(SQL Server 2008 R2 Express),其定义如下:
ID INT Auto Inc, PK
Name VARCHAR(64) Unique Key
Telephone VARCHAR(128)
我有一个存储过程,我执行它来更新表中的记录,它基本上执行以下操作:
UPDATE customers
SET Name = @name, Telephone = @Telephone
WHERE id = @id
目前,我在表格中有两个条目
ID Name Telephone
1 Fred 01234 567890
2 John 09876 543210
当我调用我的存储过程来更新 John 的电话号码时,有效执行的 SQL 是
UPDATE customers
SET Name = 'John', Telephone = '02468 135790'
WHERE id = 2
这会在 Name 字段上生成 UNIQUE KEY 冲突。现在由于 Name 字段实际上并没有改变,为什么会发生这种情况?
由于我的应用程序使用存储过程处理所有数据库操作,我可以通过删除约束并修改存储过程以手动强制执行约束来解决此问题,但这似乎是错误的。
鉴于我的表实际上有更多字段,我必须有一个通用的解决方法来防止这些错误约束问题,而不必生成大量存储过程来更新特定字段?
编辑:上表经过简化以使问题更易于管理,我很确定我没有遗漏任何重要内容,但对于信息,该表的实际定义如下
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
...和存储过程
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可以验证现有数据的选项?或者您是否有任何可能导致这种情况的触发器? -
@Bryan - 你能发布你的实际存储过程代码吗?
-
@Bryan:您在
UPDATE语句中缺少WHERE,因此目前它会尝试更新所有行。 -
天哪!不敢相信我错过了!我想是时候收工了。请张贴作为答案马丁,我会接受(并忍受让这个问题公开给所有人看到的尴尬)。
-
对名称有唯一约束可能是件好事。否则整个表都会被冲洗掉。
标签: sql sql-server stored-procedures sql-server-express