sql - 为两列的组合添加唯一约束

标签 sql sql-server

我有一张 table ,不知何故,同一个人两次进入我的 Person 表。现在,主键只是一个自动编号,但还有其他两个字段我想强制它们是唯一的。

例如,字段是:

ID  
Name  
Active  
PersonNumber  

我只需要 1 条具有唯一 PersonNumber 且 Active = 1 的记录。
(所以两个字段的组合需要唯一)

在 SQL Server 中的现有表上最好的方法是什么?我可以做到这一点,这样如果其他人使用与现有值相同的值进行插入,它就会失败,所以我不必在我的应用程序中担心这个问题代码。

最佳答案

删除重复项后:

ALTER TABLE dbo.yourtablename
  ADD CONSTRAINT uq_yourtablename UNIQUE(column1, column2);

CREATE UNIQUE INDEX uq_yourtablename
  ON dbo.yourtablename(column1, column2);

当然,在让 SQL Server 尝试插入行并返回异常(异常的代价很高)之前,首先检查是否存在这种违规通常会更好。

如果您想防止异常冒泡到应用程序,而不对应用程序进行更改,则可以使用 INSTEAD OF 触发器:

CREATE TRIGGER dbo.BlockDuplicatesYourTable
 ON dbo.YourTable
 INSTEAD OF INSERT
AS
BEGIN
  SET NOCOUNT ON;

  IF NOT EXISTS (SELECT 1 FROM inserted AS i 
    INNER JOIN dbo.YourTable AS t
    ON i.column1 = t.column1
    AND i.column2 = t.column2
  )
  BEGIN
    INSERT dbo.YourTable(column1, column2, ...)
      SELECT column1, column2, ... FROM inserted;
  END
  ELSE
  BEGIN
    PRINT 'Did nothing.';
  END
END
GO

但是,如果您不告诉用户他们没有执行插入,他们会想知道为什么数据不存在并且没有报告异常。

<小时/>

编辑这里是一个示例,它完全符合您的要求,甚至使用与您的问题相同的名称,并证明了这一点。在假设上述想法仅处理一列或另一列而不是组合之前,您应该尝试一下......

USE tempdb;
GO

CREATE TABLE dbo.Person
(
  ID INT IDENTITY(1,1) PRIMARY KEY,
  Name NVARCHAR(32),
  Active BIT,
  PersonNumber INT
);
GO

ALTER TABLE dbo.Person 
  ADD CONSTRAINT uq_Person UNIQUE(PersonNumber, Active);
GO

-- succeeds:
INSERT dbo.Person(Name, Active, PersonNumber)
  VALUES(N'foo', 1, 22);
GO

-- succeeds:
INSERT dbo.Person(Name, Active, PersonNumber)
  VALUES(N'foo', 0, 22);
GO

-- fails:
INSERT dbo.Person(Name, Active, PersonNumber)
  VALUES(N'foo', 1, 22);
GO

完成所有这些之后表中的数据:

ID   Name   Active PersonNumber
---- ------ ------ ------------
1    foo    1      22
2    foo    0      22

最后插入时出现错误消息:

Msg 2627, Level 14, State 1, Line 3 Violation of UNIQUE KEY constraint 'uq_Person'. Cannot insert duplicate key in object 'dbo.Person'. The statement has been terminated.

此外,我最近在博客中介绍了一种将唯一约束应用于以任一顺序的两列的解决方案:

关于sql - 为两列的组合添加唯一约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15800250/

相关文章:

sql - postgres 基于 if else 语句的内连接

mysql - 如何获取不重复的员工/经理表

sql-server - SQLite 国家化字符串指示器

SQL Server 的 C# 日期格式

sql-server - 通过 Azure 资源管理器从公共(public) blob 将 .bacpac 导入到 SQL Azure

sql - 如何将 SQL 消息选项卡输出插入表中?

sql - .MDF 数据库的 UnixODBC 驱动程序问题。或 : is there a way to easily extract a bunch of tables without an sql server?

sql - ActiveRecord:基于关联列的平均值对表进行排序

sql-server - 使用 BACPAC 文件将数据库从 SQL Server 迁移到 Azure

sql-server - SQLCMD.exe 退出并出现语法错误,其中不存在语法错误