字段值必须是唯一的,除非它为NULL

kri*_*ian 10 sql sql-server null sql-server-2005

我正在使用SQL Server 2005.

我有一个必须包含唯一值或NULL值的字段.我想我应该用a CHECK CONSTRAINT或a 强制执行TRIGGER for INSERT, UPDATE.

在触发器上使用约束是否有优势(反之亦然)?这样的约束/触发器可能是什么样的?

或者是否有其他更合适的选择我没有考虑过?

dot*_*joe 6

我创建了一个带有索引的视图,该索引通过where子句忽略空值...即,如果在表中插入null,则视图不关心,但如果插入非空值,则视图将强制执行约束.

create view dbo.UniqueAssetTag with schemabinding
as
select asset_tag
from dbo.equipment
where asset_tag is not null

GO

create unique clustered index ix_UniqueAssetTag
on UniqueAssetTag(asset_tag)

GO
Run Code Online (Sandbox Code Playgroud)

所以现在我的设备表有一个asset_tag列,允许多个空值但只有唯一的非空值.

注意:如果使用mssql 2000,则需要在对表执行任何插入,更新或删除之前" SET ARITHABORT ON ".很确定mssql 2005及以上版本不需要这样做.


tva*_*son 4

这是一种带有约束的替代方法。为了强制执行此约束,您需要一个函数来计算字段值出现的次数。在您的约束中,只需确保该最大值为 1 即可。

约束:

   field is null or dbo.fn_count_maximum_of_field(field) < 2
Run Code Online (Sandbox Code Playgroud)

编辑我现在不记得了——也无法检查——约束检查是在插入/更新之前还是之后完成。我想在插入/更新失败后回滚。如果我错了,上面的2应该是1。

Table函数返回一个int并使用下面的select来导出它

   declare @retVal int

   select @retVal = max(occurrences)
   from ( 
        select field, count(*) as occurrences
        from dbo.tbl
        where field = @field
        group by field
   ) tmp
Run Code Online (Sandbox Code Playgroud)

如果您的列作为(非唯一)索引,这应该相当快。