在SQL更新期间违反UNIQUE KEY约束

Bry*_*yan 13 sql sql-server stored-procedures sql-server-express

我有一个简单的数据库表(SQL Server 2008 R2 Express),其定义如下:

ID         INT          Auto Inc, PK
Name       VARCHAR(64)  Unique Key
Telephone  VARCHAR(128)
Run Code Online (Sandbox Code Playgroud)

我有一个存储过程,我执行以更新表中的记录,基本上执行以下操作:

UPDATE customers
SET    Name = @name, Telephone = @Telephone
WHERE  id = @id
Run Code Online (Sandbox Code Playgroud)

目前,我在表中有两个条目

ID   Name    Telephone
1    Fred    01234 567890
2    John    09876 543210
Run Code Online (Sandbox Code Playgroud)

当我调用我的存储过程更新John的电话号码时,有效执行的SQL是

UPDATE customers
SET    Name = 'John', Telephone = '02468 135790'
WHERE  id = 2
Run Code Online (Sandbox Code Playgroud)

这会在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
Run Code Online (Sandbox Code Playgroud)

...和存储过程

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
Run Code Online (Sandbox Code Playgroud)

Mar*_*ith 22

WHEREUPDATE语句中遗漏了它,因此它目前将尝试使用相同的值更新表中的所有行.

  • 它发生在我们最好的人身上.你问我怎么知道?:) (14认同)