为可为空的列添加唯一键 - SQL Server

时间:2013-11-03 07:06:55

标签: c# sql-server-2008-r2

我正在使用sql server 2008 R2,并希望将唯一键约束应用于可为空的列。这段代码运行良好,但如果我有多列要添加此规则,它将生成尽可能多的“nullbuster”列。

ALTER TABLE tblBranch
ADD nullbuster AS (CASE WHEN column1 IS NULL THEN BranchID ELSE NULL END);
CREATE UNIQUE INDEX UK_Column1 ON tblBranch(column1,nullbuster);

有没有办法在不生成新列的情况下实现目标。

编辑:

跟随@marc_s建议,这里创建一个唯一的键约束。 目标列是BranchCode。现在,表中有一条记录为BranchCode为NULL。当我尝试使用Null BranchCode从c#插入新记录时,它会显示错误 - 无法为唯一索引UK_BranchCode插入重复键。 但是,当我在数据库中手动插入记录时,它确实接受空值。 我哪里错了。

CS

Guid gId = Guid.NewGuid();
cmd = new sqlcommand("insert into tblBranch(BranchId,BranchCode) 
                      values(@BranchId,@BranchCode)",con);
cmd.Parameters.AddWithValue("@BranchId",gId);
cmd.Parameters.AddWithValue("@BranchCode",txtBranchCode.Text);//empty text here
con.Open();
cmd.ExecuteNonQuery();
cmd.Close();

3 个答案:

答案 0 :(得分:2)

因此,您要为要编制索引的每个可空列创建nullbuster列?看起来像是矫枉过正......

为那些可以为空的列创建过滤索引不会更容易,例如:

CREATE UNIQUE INDEX UK_Column1 ON tblBranch(column1) WHERE column1 IS NOT NULL;

因此允许任意数量的NULL条目,同时唯一地索引其他值。这样,您无需添加所有nullbuster列,只是为了使索引成为可能......

详细了解已过滤的索引:

更新:为了将参数设置为 NULL (而不是空字符串),请使用以下代码:

if(string.IsNullOrEmpty(txtBranchCode.Text))
{
    cmd.Parameters.AddWithValue("@BranchCode", DBNull.Value);
}
else
{
    cmd.Parameters.AddWithValue("@BranchCode", txtBranchCode.Text);
}

答案 1 :(得分:1)

使用marc_s提供的过滤索引建议。你说你仍然得到一个独特的索引违规。这告诉你什么?它告诉您正在插入关于索引定义的重复键。你想,你不是,但你肯定是。

如何调试?你看看你插入的是什么。您在调试器中查看gIdtxtBranchCode.Text。另外,您查看错误消息,因为它显示:

  

重复键值为...

所有这些线索都会让您发现txtBranchCode.Text不是null,而是一个空字符串。请改为插入NULL

答案 2 :(得分:0)

我建议你将column1移动到一个新表并使其唯一且不可为空。使用新表中的外键引用Branch表。仅在您具有column1的(非null)值的位置填充新表。

创建新表是支持column1上任何依赖项的最可靠方法。允许空值的列不是列,但显然应该是column1。将该列放入新表中也恰好是满足Normal Form的唯一方法,除非你有一个非常令人信服的理由将column1“非规范化”到Branch表中,它似乎不属于它