今天同學向我提了乙個問題,是sql server中乙個關於「如何保證可空字段中非空值唯一」的問題,我覺得蠻有意思,現記錄下來大家**下。
問題是:在乙個表裡面,有乙個允許為空的字段,空是可以重複的,但是不為空的值需要唯一。
表結構如下面**建立
createtable
test_tb
( testid
intnot
null
identity(1,1)
primary
key,
caption nvarchar(100)
null
);
go
解決方案:索引建立好了,我們來測試下效果解決方案1:
對於這個問題,大家的第乙個想法可能是:在caption這個字段上面加乙個唯一鍵不就可以了嗎?好,我們按著這個思路做下去,先建立唯一索引。
create
unique
nonclustered
index
un_test_tb
ontest_tb(caption)
go
insert執行之後我們會收到下面的錯誤資訊:into
test_tb (caption)
values
(null
) go
insert
into
test_tb (caption)
values
(null
) go
訊息 2601,級別 14,狀態 1,第 1 行所以該解決方案是不行的。不能在具有唯一索引
'un_test_tb'
的物件
'dbo.test_tb'
中插入重複鍵的行。
語句已終止。
解決方案2:
新增約束,讓sql server在插入資料的時候,先驗證下已有資料中是否有現在要插入的這個值。由於這個約束不是簡單的乙個運算,因此我們先建立乙個函式,然後再在約束中呼叫這個函式。
建立驗證邏輯函式:
create在約束中引用函式:function
[dbo].[fn_ck_test_tb_caption]()
returns
bitas
begin
if(exists(
select
1 from
test_tb
asa
where
(caption
isnot
null
) and
exists
(select
1 as
expr1
from
test_tb
where
(caption
isnot
null
) and
(caption = a.caption)
and(a.testid <> testid))
))
return
0 return
1 end
go
alter現在來測試下效果。先來測試null值table
test_tb
addconstraint
ck_test_tb_caption
check
(dbo.fn_ck_test_tb_caption() = 1)
go
insert可以成功執行,而且也出了多行為null的情況。現在再來測試不為空的插入情況。into
test_tb (caption)
values
(null
) go
insert
into
test_tb (caption)
values
(null
) go
select
* from
test_tb
go
insert結果是在第三條語句的時候報錯了,表中的caption欄位也有'aaa'和'bbb'了,這也正好是我們要的結果。into
test_tb (caption)
values
(n'aaa'
) go
insert
into
test_tb (caption)
values
(n'bbb'
) go
insert
into
test_tb (caption)
values
(n'bbb'
) go
select
* from
test_tb
go
所以解決方案2是正確的。但是為了這麼乙個小小功能,就寫這麼長一段東西是不是太繁瑣了呢?我們來看下面的解決方案。
解決方案3:(只適用於sql server 2008)
sql server 2008中有了乙個優雅的解決方案,那就是篩選索引。篩選索引是一種經過優化的非聚集索引,尤其適用於涵蓋從定義完善的資料子集中選擇資料的查詢。篩選索引使用篩選謂詞對錶中的部分行進行索引。有了篩選索引,我們只需要寫一條語句就達到上面的效果。
create再用上面的一些測試語句來測試的話,會發現完全是達到了我們的要求。unique
nonclustered
index
un_test_tb
ontest_tb(caption)
where
caption
isnot
null
go
這個方案的唯一缺點就是該語句只有sql server 2008支援。。
不知道各位有沒有又優雅又適用於各個版本的sql server的解決方案,望不勝賜教。
SQL Server如何保證可空字段中非空值唯一
今天同學向我提了乙個問題,是sql server中乙個關於 如何保證可空字段中非空值唯一 的問題,我覺得蠻有意思,現記錄下來大家 下。問題是 在乙個表裡面,有乙個允許為空的字段,空是可以重複的,但是不為空的值需要唯一。表結構如下面 建立 create table test tb testid int...
SQL Server如何保證可空字段中非空值唯一
今天同學向我提了乙個問題,是sql server中乙個關於 如何保證可空字段中非空值唯一 的問題,我覺得蠻有意思,現記錄下來大家 下。問題是 在乙個表裡面,有乙個允許為空的字段,空是可以重複的,但是不為空的值需要唯一。表結構如下面 建立 create table test tb testid int...
SQL Server如何保證可空字段中非空值唯一
今天同學向我提了乙個問題,是sql server中乙個關於 如何保證可空字段中非空值唯一 的問題,我覺得蠻有意思,現記錄下來大家 下。問題是 在乙個表裡面,有乙個允許為空的字段,空是可以重複的,但是不為空的值需要唯一。表結構如下面 建立 create table test tb testid int...