2013-02-01 51 views
2

誰知道如何在兩列中允許使用NULLS的情況下創建2列的唯一約束?我的意思是忽略col1 = NULL和col2 = NULL的唯一性,但是讓約束在只有其中一個爲NULL的情況下工作?我發現如何做到單列(How do I create a unique constraint that also allows nulls?),但不能爲2列。這裏是我的腳本,現有記錄的(多個NULL,NULL是允許的)的作品,但不會讓添加任何新NULL,NULL記錄:如何爲2個可爲空的列添加唯一約束?

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

UPDATE:嗯,它可以讓你添加新的(NULL,NULL )值,所以我錯了,但它也可以讓你添加像(1,NULL),(1,NULL),我不希望是,所以唯一性應該適用於這種情況下,只有多個(NULL,NULL)應該被)允許。這個怎麼做?

回答

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 
+0

權,你的腳本能正常工作,我可以猜測用戶界面插入空值,而不是空值。我會調查它。謝謝 – YMC

+0

發現其他問題,請參閱更新的問題 – YMC

1

如果您希望這些值是唯一的不同之處時,都爲null,這意味着你希望他們是唯一的,只要至少有一個值不爲空。您的索引過濾器有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將only let you create a where clause with AND conditions。你也can't use a persisted computed column做到這一點。

相反,你可以是創建於原始表的索引視圖,然後把唯一索引。這有點重量級,但它應該工作。

所以......借用@ 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