【发布时间】:2010-08-11 18:58:02
【问题描述】:
我有一列应该包含 2 power n: 2,4,8,16,32 等值之一。我想在表架构级别强制执行 - 有没有办法指定这样的列约束?
谢谢!
【问题讨论】:
-
你能说出你这样做的原因吗?
-
好吧,我突然想到我应该存储 n 而不是 2 power n :) 案例解决了!
标签: sql sql-server constraints
我有一列应该包含 2 power n: 2,4,8,16,32 等值之一。我想在表架构级别强制执行 - 有没有办法指定这样的列约束?
谢谢!
【问题讨论】:
标签: sql sql-server constraints
无耻地从 this answer 窃取你可以使用按位运算来非常有效地做到这一点。
ALTER TABLE tablename ADD CONSTRAINT
ckname CHECK (colName > 0 AND (colName & (colName - 1) =0))
【讨论】:
在 SQL Server 中:
ALTER TABLE [dbo].[PowerOfTwo]
WITH CHECK ADD CONSTRAINT [CK_PowerOfTwo]
CHECK ((log([Value])/log(2)=round(log([Value])/log(2), 0, 1)))
【讨论】:
如何将列定义为 N。那么根据定义,该列的所有用途将是 2^n,而不是约束。
否则 - 您可以放置触发逻辑以在输入或更新每个值时对其进行验证。
【讨论】:
假设您的列名是 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。
分享和享受。
【讨论】:
创建列检查:
CHECK (column_name IN (2, 4, 8, 16, 32, ..., 2147483648))
【讨论】:
log 4 次,但除了那个(不相关的)差异之外,没有别的了。或者您是否暗示您的专栏实际上是 double 类型,而不是 int ?在这种情况下,接受的答案也是错误的,因为浮点精度有限,因此比较可能不如您预期的那样真实。