16

我想知道为什么 Oracle 在VARCHAR2.

我认为这是为了约束。NUMBERoracle 将此参数作为dataType之类的可选参数会是更好的选择吗?

我经常在将旧表调整为更大的大小时遇到​​问题,因为有时一个值大于VARCHAR2列的大小定义。

定义VARCHAR2(10) 或VARCHAR2(1000).

我想,这是一个不必要的约束。如果不是,您是否知道这种约束导致某些有用的真实案例?为什么在NUMBERtype 中没有这样的声明?

4

6 回答 6

24

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

不,这根本不是一回事。

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

……

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以科学计数法存储数值,因此数字的算术大小与其消耗的存储空间之间没有直接的关系。

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> 

尽管如此,尽可能指定比例和精度仍然是一种很好的做法,尤其是在我们处理整数或货币时。

于 2010-02-11T13:41:04.843 回答
8

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

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

您可以查看 SYS.STANDARD 包以了解如何声明 VARCHAR2 子类型。例如,如果您想要自己的“字符串”类型,您可以在不附加长度规范的情况下使用它,您可以尝试:

SUBTYPE MY_STRING IS VARCHAR2(4000);

但是,如果您要为有问题的列编制索引,请注意这一点(正如@APC 前面指出的那样)。

我同意我宁愿能够声明一个字符串(顺便说一句,在 SYS.STANDARD 中定义为 VARCHAR2 的子类型),而不必声明一个长度,但这不是 Oracle 的工作方式,就像我一样我不打算开始编写我自己的关系数据库(我有自己的风车可以倾斜,谢谢 :-) 我只会顺应现状。

我希望这有帮助。

于 2010-02-11T14:11:23.597 回答
5

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

不过实话说:

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

于 2010-02-11T03:57:48.300 回答
3

即使它没有像 char 字段那样在磁盘上分配一定数量的字节,仍然有适当的理由来调整大小:

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

我敢肯定还有其他人能想到的更多原因,但这些是我在过去的项目中看到的,有人选择了varchar2(4000)一切。

于 2010-02-11T00:15:33.580 回答
3

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

或者购买非常大的信封。

于 2010-02-11T05:24:35.983 回答
0

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

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

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

于 2016-01-18T13:44:54.450 回答