为什么Oracle varchar2具有强制大小作为定义参数?

时间:2010-02-10 23:52:28

标签: oracle varchar2

我想知道为什么Oracle需要VARCHAR2定义中的size参数。

我认为这是为了制约。 oracle将此参数作为可选的NUMBER dataType?

是一个更好的选择

我经常在将旧表格调整为较大尺寸时遇到问题,因为有时值会大于VARCHAR2列的尺寸定义。

定义VARCHAR2(10)或VARCHAR2(1000)的类型是一样的。

我想,这是一个不必要的约束。如果没有,你知道这个约束导致一些有用的真实案例吗?为什么在NUMBER类型中没有这样的声明?

6 个答案:

答案 0 :(得分:24)

  

定义一种类型是一样的   varchar2(10)或varchar2(1000)。

不,这根本不是一回事。

  1. 列的长度是开发人员构建屏幕的有用元数据。
  2. 同样,TOAD和SQL Developer等自动查询工具在渲染结果时会使用列的长度。
  3. 数据库在为PL / SQL集合分配内存时使用变量的长度。由于内存来自PGA超大变量声明可能导致程序失败,因为服务器内存不足。
  4. PL / SQL程序中单个变量的声明存在类似的问题,只是集合倾向于使问题成倍增加。
  5. 超大列会为复合索引带来问题。以下是关于具有8K块的数据库
  6. ...

    SQL> create table t23 (col1 varchar2(4000), col2 varchar2(4000))
      2  /
    
    Table created.
    
    SQL> create index t23_i on t23(col1,col2)
      2  /
    create index t23_i on t23(col1,col2)
                          *
    ERROR at line 1:
    ORA-01450: maximum key length (6398) exceeded
    
    
    SQL>
    

    但最重要的是,列大小是一种错误检查形式。如果该列应该是十个字符长,并且一些自主进程试图加载一千个字符,则出现问题。这个过程应该失败,所以我们可以调查我们为什么要加载duff数据。另一种选择是一个充满垃圾的数据库,如果这是我们想要的东西,我们应该给每个人提供Excel并完成它。

    确实,当我们低估时改变列大小可能会令人厌烦。但它并不经常发生,我们可以通过在PL / SQL中使用%TYPE和SUBTYPE声明而不是硬编码变量来减轻很多痛苦。


      

    “为什么在NUMBER类型中没有这样的声明”

    数字不同。首先,数字的最大大小远小于文本等效项(保证精度的38位数)。

    但关键的区别在于Oracle存储数值in scientific notation,因此数字的算术大小与其消耗的存储空间之间没有直接的关系。

    SQL> select vsize(123456789012345678901) n1
      2         , vsize(999999999999999999999999999999) n2
      3         , vsize(0.000000000000000000001) n3
      4         , vsize(1000000000000000000000000) n4
      5  from dual
      6  /
    
            N1         N2         N3         N4
    ---------- ---------- ---------- ----------
            12         16          2          2
    
    SQL> 
    

    尽管如此,在可能的情况下指定比例和精度仍然是一个好习惯,特别是当我们处理整数,比如说或金钱时。

答案 1 :(得分:7)

我认为记住关系数据库的历史背景是很重要的。在它们被开发的时候(70年代末期 - 80年代初期),通常可用的计算机比现在的计算机要小得多(在内存和磁盘空间方面)和功能不强(在CPU方面),并且管理这些资源必然是令人信服的关注。 COBOL是商业计算的通用语言(并且仍然被广泛使用),并且面向对象的语言(例如Smalltalk和C ++)在所有实际应用中都是未知的。那时,预计程序将准确地声明每个数据元素需要多少存储空间,例如:字符串为10个字节,短整数为2个字节,浮点数为4个字节,等等,因此当时新开发的关系数据库使用了这种声明方式。更重要的是,假设表明每个数据元素都会(隐式或显式地)声明它所需的存储量,并且这已经在非常基础的级别上编码到关系引擎中。

现在,随着时间的推移,这个要求已经有所放松,至少就磁盘上的数据存储而言。我相信在Oracle中,NUMBER数据类型将灵活地分配空间,以便实际只使用存储其值所需的最小空间量,并且VARCHAR2列将仅使用足够的磁盘空间来存储实际数据而不存储尾随空白,虽然您仍需要声明VARCHAR2所需的最大存储量。

您可以查看SYS.STANDARD包以了解如何声明VARCHAR2子类型。例如,如果你想要自己的'字符串'类型,你可以使用它而无需修改长度规范,你可以尝试:

SUBTYPE MY_STRING IS VARCHAR2(4000);

但是,如果您要对相关列进行索引(如前面的@APC所指出的那样),请注意这一点。

我同意我只是能够声明一个STRING(即BTW,在SYS.STANDARD中定义为VARCHAR2的子类型)而不必声明长度,但这不是Oracle的工作原理,并且因为我不打算开始编写我自己的关系数据库(我有自己的风车可以倾斜,谢谢:-)我会跟上现状。

我希望这会有所帮助。

答案 2 :(得分:5)

为什么不将每个数据库表中的每一列都设为CLOB?这样你就不用担心最大长度...

但是,严肃地说:

数据类型长度约束与任何约束的原因相同:它们通过确保表中成功存储的任何数据符合您的约束,减少了需要在所有应用程序代码中进行的错误检查。已定义。

答案 3 :(得分:3)

即使它没有像char字段那样在磁盘上分配一定数量的字节,但仍有合理的原因:

  • 数据读取器上的内存分配(基于最大行大小)
  • 索引大型列会使块大小发挥作用
  • 等等...

我确信其他人可以想到更多的理由,但那些是我在过去的项目中看到的,有人选择了varchar2(4000)所有内容。

答案 4 :(得分:3)

从提取信息的角度来看,了解这个领域有多大是非常有用的。例如,如果您必须在信封上打印地址或在屏幕上显示地址,您想知道该字段的大小。

或购买非常大的信封。

答案 5 :(得分:0)

可能会对性能造成影响:在MySQL中,temporary tablesMEMORY tablesVARCHAR列存储为固定长度的列,并填充到其最大长度。

如果您设计的VARCHAR列比您需要的最大尺寸大,那么您将消耗更多内存。这会影响cache efficiency, sorting speed, etc

所以你给出字符串下面的最大长度。就像你最大字符10的长度所以不要给他的长度100或更多。