2010-08-11 181 views
2

我有一列應該包含一個值爲2的冪n:2,4,8,16,32等。我想強制在表模式級別上 - 是有一種方法來指定這樣的列約束?在表上設置列約束(SQL Server)

謝謝!

+0

你能給出一個理由,爲什麼你這樣做? – JonH 2010-08-11 19:01:26

+0

好的,它只是我想我應該存儲n比2電源n :)案例解決! – Andrey 2010-08-11 19:11:54

回答

4

在SQL Server:

ALTER TABLE [dbo].[PowerOfTwo] 
WITH CHECK ADD CONSTRAINT [CK_PowerOfTwo] 
CHECK ((log([Value])/log(2)=round(log([Value])/log(2), 0, 1))) 
1

假設你的列名是N.試着這麼做

CHECK(LOG(N)/LOG(2) = TRUNC(LOG(N)/LOG(2))) 

的目的是驗證值N的二進制數是一個整數,這將意味着n爲2的冪不確定SQL Server是否支持LOG和TRUNC功能 - 根據需要替換爲正確的名稱。

編輯:當我重讀這篇文章時,我意識到舍入可能會導致一個問題(我忘記了浮點的第二條命令,即:您不應該比較浮點值的平等!)。好的,

CHECK(ABS(LOG(N)/LOG(2) - TRUNC(LOG(N)/LOG(2))) < 0.00001) 

或用0.00001代替任何錯誤容差。

分享和享受。

+0

好的,謝謝! – Andrey 2010-08-11 19:16:17

0

創建一個列檢查:

CHECK (column_name IN (2, 4, 8, 16, 32, ..., 2147483648)) 
+0

降低任何人的原因? – GSerg 2010-08-11 19:12:14

+1

你是認真的嗎? – Andrey 2010-08-11 19:13:45

+0

是的,我認真。這個答案在概念上與接受的答案有什麼不同?是的,我認爲使用一個簡單的值列表會更好,因爲有很少的值,而不是調用'log'四次,但除此之外(不相關)的差異,沒有別的。或者你是暗示你的列實際上是'double'類型,而不是'int'?在這種情況下,接受的答案也是錯誤的,因爲有一個有限的浮點精度,因爲比較結果可能不如預期的那麼真實。 – GSerg 2010-08-11 19:24:58

2

怎麼樣定義列是N.然後該列的所有用途將是2^N的定義,而不是約束。

否則 - 您可以將觸發邏輯放置在驗證輸入或更新每個值時使用。

+0

我已經想出了幾分鐘之前:)無論如何,我會讓你高興,因爲它是一個好主意 – Andrey 2010-08-11 19:15:18

5

this answer無恥偷你可以使用位操作,以漂亮有效做到這一點。

ALTER TABLE tablename ADD CONSTRAINT 
    ckname CHECK (colName > 0 AND (colName & (colName - 1) =0)) 
+0

但不如蘭迪的答案效率... ... – 2010-08-11 19:28:51