2

谁知道如何为两列中允许 NULLS 的 2 列集创建唯一约束?我的意思是忽略 col1=NULL 和 col2=NULL 的唯一性,但是让约束在其中只有一个为 NULL 的情况下起作用?我发现如何为单列执行此操作(如何创建一个也允许空值的唯一约束?),但不能为 2 列。这是我的脚本,适用于现有记录(允许多个 NULL,NULL),但不允许添加任何新的 NULL,NULL 记录:

CREATE UNIQUE NONCLUSTERED INDEX MyIndex ON dbo.MyTable(col1, col2)     
WHERE col1 IS NOT NULL AND col2 IS NOT NULL

更新:好吧,它可以让你添加新的 (NULL, NULL) 值,所以我错了,但是它也可以让你添加我不希望的 (1, NULL), (1, NULL) 之类的东西,所以唯一性应该在这种情况下工作,应该只允许多个 (NULL, NULL)。这个怎么做?

4

2 回答 2

2

其他的东西肯定是行不通的。您的代码/脚本按预期工作:

CREATE TABLE #MyTable
(
    Col1 INT NULL,
    Col2 INT NULL
)

CREATE UNIQUE NONCLUSTERED INDEX MyIndex ON #MyTable(col1, col2)     
WHERE col1 IS NOT NULL AND col2 IS NOT NULL

INSERT INTO #MyTable(Col1, Col2)
VALUES(NULL, NULL) --Works

INSERT INTO #MyTable(Col1, Col2)
VALUES(NULL, NULL) --Works

SELECT * FROM #MyTable

INSERT INTO #MyTable(Col1, Col2)
VALUES(1, 1) --Works

INSERT INTO #MyTable(Col1, Col2)
VALUES(1, 1) --Fails

SELECT * FROM #MyTable

DROP TABLE #MyTable
于 2013-02-01T16:06:42.203 回答
1

如果您希望值是唯一的,除非两者都为空,这意味着您希望它们是唯一的,只要至少一个值不为空。您对索引的过滤器有一个AND,但您需要一个OR.

CREATE UNIQUE NONCLUSTERED INDEX MyIndex ON dbo.MyTable(col1, col2)     
WHERE col1 IS NOT NULL OR col2 IS NOT NULL -- (note: doesn't work)

但是……你不能这样做。SQL Server只允许您创建带有 AND 条件的 where 子句。您也不能使用持久计算列来执行此操作。

相反,您可以做的是在原始表上创建一个索引视图,然后将唯一索引放在该表。它有点重量级,但它应该可以工作。

所以......借用@Meff的脚本,你正在看类似的东西:

CREATE TABLE dbo.MyTable
(
    Col1 INT NULL,
    Col2 INT NULL
)
GO
CREATE VIEW dbo.MyTableUniqueView WITH SCHEMABINDING AS
SELECT Col1, Col2 FROM dbo.MyTable
WHERE Col1 IS NOT NULL OR Col2 IS NOT NULL 
GO
CREATE UNIQUE CLUSTERED INDEX MyTableUniqueIndex
ON dbo.MyTableUniqueView(Col1, Col2)
GO
INSERT INTO MyTable(Col1, Col2)
VALUES(NULL, NULL) --Works

INSERT INTO MyTable(Col1, Col2)
VALUES(NULL, NULL) --Works

SELECT * FROM MyTable

INSERT INTO MyTable(Col1, Col2)
VALUES(1, 1) --Works

INSERT INTO MyTable(Col1, Col2)
VALUES(1, 1) --Fails

INSERT INTO MyTable(Col1, Col2)
VALUES(1, null) --Works

INSERT INTO MyTable(Col1, Col2)
VALUES(1, null) --Fails

SELECT * FROM MyTable
GO
DROP VIEW MyTableUniqueView
DROP TABLE MyTable
于 2013-02-01T16:13:16.067 回答