Oracle主键:NUMBER与NUMBER(7,0)

时间:2009-08-05 17:27:14

标签: oracle primary-key

指定PK的精度有什么好处吗?鉴于可能永远不会有超过几千条记录,7,0是否足够?

没有指定精度的危险吗?

3 个答案:

答案 0 :(得分:10)

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中,NUMBER被存储为归一化为0.01 <= N < 1并以指数为前缀的数值的十进制数字。

在上面的示例中:

  • 196是基于192的指数(4)。
  • 10是十进制9
  • 100是十进制99

整数以小数形式显示为00.09 99 99 99 * (100 ^ 4) = 9,999,999

满足所要求的精度所需的位数越多,当然会存储的数字越多。

当您将精确值插入精度较低的列时,它只会舍入到列的精度并存储为圆形。

因此,声明列NUMBER(38)在性能上是安全的,因为它意味着没有超过NUMBER(7, 0)的开销(对于适合这两种类型的数字)。

但是,如果您的PRIMARY KEY本质上是整数,则最好将精度指定为0,以确保没有小数值到达您的表格。

<强>更新

@Mac还指出客户端可能依赖列数据类型来确定值域。

如果您的申请需要INT32,则应将您的号码设为NUMBER(9)或更低(或您的客户认为可转换为Int32的任何类型)。

答案 1 :(得分:4)

在问题的数据库方面,我无法添加到Quassnoi's answer

但值得注意的是,它可能会对访问数据库的应用程序产生影响(或者更准确地说,对这些应用程序的开发人员产生影响)。例如,在.NET中,如果您获得包含主键的IDataRecord(使用ODP .NET),当您的列定义为NUMBER(38)并且成功时,对GetInt32的调用将很可能失败定义为NUMBER(7)(即使该值在正确范围内时)。

答案 2 :(得分:2)

如果你不期望超过,比如表中的100K记录,如果你用N(7,0)指定PK,如果一些失控过程最终溢出PK,你将得到一个早期警告。如果你用N(38)指定它,警告可能不会那么早出现。

我总是错误地将尺寸限制在“产品寿命”的最小尺寸,并有合理的误差幅度。