【发布时间】:2009-08-07 17:59:39
【问题描述】:
在 PK 上指定精度有什么好处吗?考虑到可能永远不会超过几千条记录,7,0 是否足够?
不指定精度有什么危险吗?
【问题讨论】:
标签: oracle primary-key
在 PK 上指定精度有什么好处吗?考虑到可能永远不会超过几千条记录,7,0 是否足够?
不指定精度有什么危险吗?
【问题讨论】:
标签: oracle primary-key
NUMBER(7, 0) 只是限制值域。
他们的内部表示没有区别:
CREATE TABLE t_pk (col1 NUMBER(7, 0) NOT NULL, col2 NUMBER(38) NOT NULL)
INSERT
INTO t_pk
VALUES (9999999, 9999999)
SELECT DUMP(col1), DUMP(col2)
FROM t_pk
DUMP(col1) DUMP(col2)
--- ---
Typ=2 Len=5: 196,10,100,100,100 Typ=2 Len=5: 196,10,100,100,100
在Oracle 中,NUMBERs 存储为归一化为0.01 <= N < 1 并以指数开头的数值的百分位数。
在上面的例子中:
196 是基于 192 的指数 (4)。10 是十进制 9
100's 是十进制 99's整数在十进制中读取为00.09 99 99 99 * (100 ^ 4) = 9,999,999
为了满足要求的精度,需要的位数越多,当然要存储的位数越多。
当您将精确值插入不太精确的列中时,它只会四舍五入到列的精度并以四舍五入的形式存储。
因此,声明 NUMBER(38) 列在性能方面是安全的,因为这意味着在 NUMBER(7, 0) 上没有开销(对于适合这两种类型的数字)。
但是,如果您的 PRIMARY KEYs 本质上是整数,则最好将精度指定为 0 以确保不会有小数值进入您的表。
更新:
@Mac 还指出客户端可能依赖列数据类型来确定值域。
如果您的应用程序需要INT32,您应该将您的号码设为NUMBER(9) 或以下(或您的客户认为可转换为Int32 的任何类型)。
【讨论】:
在问题的数据库方面,我没有什么要添加到Quassnoi's answer。
但值得注意的是,它也可能对访问数据库的应用程序产生影响(或者更准确地说,对这些应用程序的开发人员产生影响)。例如,在 .NET 中,如果你得到一个包含主键的 IDataRecord(使用 ODP .NET),当你的列定义为 NUMBER(38) 时,对 GetInt32 的调用将失败,而当定义为 NUMBER( 7) (即使值在正确的范围内)。
【讨论】:
如果您预计表中的记录不超过 100K,如果您使用 N(7,0) 指定 PK,如果某个失控进程最终溢出 PK,您将收到早期警告。如果你用 N(38) 指定它,警告可能不会这么早出现。
在将尺寸限制为“产品寿命”预期的最小尺寸方面,我总是会犯错,并留有合理的误差范围。
【讨论】: