【问题标题】:Oracle primary keys: NUMBER vs NUMBER(7,0)Oracle 主键:NUMBER 与 NUMBER(7,0)
【发布时间】:2009-08-07 17:59:39
【问题描述】:

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

不指定精度有什么危险吗?

【问题讨论】:

    标签: oracle primary-key


    【解决方案1】:

    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 的任何类型)。

    【讨论】:

      【解决方案2】:

      在问题的数据库方面,我没有什么要添加到Quassnoi's answer

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

      【讨论】:

      • +1,好点。我总是忘记人们需要用他们选择的值在数据库之外做一些事情:)
      【解决方案3】:

      如果您预计表中的记录不超过 100K,如果您使用 N(7,0) 指定 PK,如果某个失控进程最终溢出 PK,您将收到早期警告。如果你用 N(38) 指定它,警告可能不会这么早出现。

      在将尺寸限制为“产品寿命”预期的最小尺寸方面,我总是会犯错,并留有合理的误差范围。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-02-16
        • 2019-03-22
        • 2015-03-28
        • 1970-01-01
        • 2016-03-23
        • 1970-01-01
        相关资源
        最近更新 更多