我正在使用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();
答案 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提供的过滤索引建议。你说你仍然得到一个独特的索引违规。这告诉你什么?它告诉您正在插入关于索引定义的重复键。你想,你不是,但你肯定是。
如何调试?你看看你插入的是什么。您在调试器中查看gId
和txtBranchCode.Text
。另外,您查看错误消息,因为它显示:
重复键值为...
所有这些线索都会让您发现txtBranchCode.Text
不是null,而是一个空字符串。请改为插入NULL
。
答案 2 :(得分:0)
我建议你将column1移动到一个新表并使其唯一且不可为空。使用新表中的外键引用Branch表。仅在您具有column1的(非null)值的位置填充新表。
创建新表是支持column1上任何依赖项的最可靠方法。允许空值的列不是键列,但显然应该是column1。将该列放入新表中也恰好是满足Normal Form的唯一方法,除非你有一个非常令人信服的理由将column1“非规范化”到Branch表中,它似乎不属于它