2

我正在使用 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。当我尝试从 c# 插入一条带有 Null BranchCode 的新记录时,它给出了一条错误消息 - 无法为唯一索引 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();
4

3 回答 3

3

因此,您要为要索引的每个可为空的列创建一个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);
}
于 2013-11-03T07:54:35.753 回答
1

使用 marc_s 提供的过滤索引建议。您说您仍然遇到唯一索引违规。这告诉你什么?它告诉您您正在插入与索引定义相关的重复键。你认为,你不是,但你肯定是。

如何调试?你看看你正在插入什么。您在调试器中查看gId和。txtBranchCode.Text另外,您查看错误消息,因为它说:

重复的键值是...

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

于 2013-11-03T16:54:10.950 回答
0

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

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

于 2013-11-03T21:23:38.210 回答