問題:
當我需要在表格中增加一個必須被唯一定義的柱狀表時,發現SQL Server允許在一個柱狀表上定義一個UNIQUE constraint。但是我也可以在柱狀表上創造一個Unique Index。哪一個是我應該使用的?
專家解答:
這兩種方法之間的不同是很微妙的,UNIQUE constraints是ANSI SQL定義的一部分,定義UNIQUE constraints是數據庫邏輯定義的一部分。另外,UNIQUE constraints作為一個副產品可以作為表格定義的一部分被創造,當約束被創造時SQL Server將自動的在搜索引擎下創造一個Unique Index。相反的,定義Unique Index是設計物理數據模型的一部分,他們不是ANSI標准。
從性能立場上,UNIQUE constraints 和 unique indexes對最優化查詢同樣有效,這兩個在使用過程中,你不會覺得其中一個比另一個更有效。在我看來,我堅持ANSI標准,通過約束實現柱體唯一性。在我看來UNIQUE constraints在更好的證明一個表格時有用,我使用它們超過unique indexes
在一個Management Studio連接中,運行下列的程序去創造一個表格被叫做CAR。表格基於它的構成和模型定義一個UNIQUE constraint在CAR上。
CREATETABLEdbo.CAR
(
CARIDINTIDENTITY(1,1)NOTNULL,
MAKEVARCHAR(10)NOTNULL,
MODELVARCHAR(10)NOTNULL,
TOTALDOORSTINYINTNOTNULL,
TOTALCYLINDERSTINYINTNOTNULL,
CONSTRAINTPK_CARPRIMARYKEYNONCLUSTERED(CARID),
CONSTRAINTUQ_CARUNIQUENONCLUSTERED(MAKE,MODEL)
)
GO
運行SP_HELP CAR顯示,the engine已經創造了包括這個約束和一個索引支持在內。
圖一:運行SP_HELP CAR
一個要求出現在我的桌面上。以報告為目的,管理想要通過year made跟蹤cars,另外,對結構和模型。我們將改變這個表格使之包含一個年柱。
ALTERTABLEDBO.CAR
ADD[YEAR]SMALLINT
GO
增加這個柱體要求我去改變約束的唯一性,否則,我將無法通過結構和模型而不管年柱增加比一個多的car。另外,不允許通過結構,模型和年柱復制cars可能是一個好的主意。結果是我將重新創作這個約束的Unique Index去包含年柱。
DROPINDEXDBO.CAR.UQ_CAR
GO
CREATEUNIQUEINDEXUQ_CARONDBO.CAR(MAKE,MODEL,[YEAR])
GO
運行上方的代碼,你將看見隨後的錯誤提示:
圖二:錯誤提示伙計,這個看起來丑陋吧。DROP失敗是因為約束依靠索引,它必須匹配約束的定義。在我們的例子中去改變唯一性,我們可以先drop然後重復增加約束。
ALTERTABLEDBO.CAR
DROPCONSTRAINTUQ_CAR
GO
ALTERTABLEDBO.CAR
ADDCONSTRAINTUQ_CARUNIQUE(MAKE,MODEL,[YEAR])
GO
重新運行SP_HELP CAR,顯示有改變在進行。
圖三:第二次運行SP_HELP CAR
我剛剛注意到在表格上沒有clustered index。自從我們的所有報告將按照結構,模型和年柱分類,我就想將unique constraint轉化為clustered index。同時你又可以DROP 以及 CREATE這個約束使它成為UNIQUE CLUSTERED,實際上你也可以使用CREATE INDEX使用DROP_EXISTING選項。自從約束的約束匙不再改變,SQL Server engine 將允許你去發行下列的的聲明,將UNIQUE constraint改變為clustered。
CREATEUNIQUECLUSTEREDINDEXUQ_CARONDBO.CAR(MAKE,MODEL,[YEAR])
WITHDROP_EXISTING
GO
再次運行SP_HELP CAR顯示constraint's index被改變成clustered index
圖四:第三次運行SP_HELP CAR