25

创建表:

CREATE TABLE test (
charcol    CHAR(10),
varcharcol VARCHAR2(10));

SELECT LENGTH(charcol), LENGTH(varcharcol) FROM test;

结果:

LENGTH(CHARCOL) LENGTH(VARCHARCOL)
--------------- ------------------
             10                  1 

请让我知道 Varchar2 和 char 有什么区别?我们什么时候同时使用两者?

4

7 回答 7

30

尽管已经有几个答案正确描述了 的行为char,但我认为需要说的是,除了三种特定情况外,您不应该使用它:

  1. 您正在构建一个固定长度的文件或报告,并为 a 分配一个非空值char避免了编写rpad()表达式的需要。例如,如果firstnamelastname都定义为char(20),则创建firstname || lastname的更短的写法。rpad(firstname,20) || rpad(lastname,20)Chuck Norris
  2. 您需要区分显式空字符串''null. 通常它们在 Oracle 中是一样的,但是分配''给一个char值会触发它的空白填充行为,而null不会,所以如果区分差异很重要,而且我真的想不出为什么会这样,那么你有办法做到这一点。
  3. 您的代码是从某些其他系统移植(或需要兼容)由于遗留原因需要空白填充的。在那种情况下,你会坚持下去,我很同情你。

确实没有理由char仅仅因为某些长度是固定的(例如Y/N标志或 ISO 货币代码,例如'USD')而使用。它不是更有效,它不节省空间(没有神话般的 a 长度指示符varchar2,只有一个空白填充开销char),并且它不会阻止任何人输入较短的值。(如果您'ZZ'在您的char(3)货币列中输入,它只会被存储为'ZZ '。)它甚至无法与曾经依赖它的某些古老版本的 Oracle 向后兼容,因为从来没有。

并且传染可以传播,因为(遵循最佳实践)您可以使用类似sales.currency%type. 现在您的l_sale_currency变量是一个隐形变量char,对于较短的值(或 ),它会以不可见的空白填充,从而为隐藏不相等''的错误打开了大门,即使您将它们都分配给了它们。l_sale_currencyl_refund_currency'ZZ'

有人争辩说char(n)(其中n是某个字符长度)表明值应该是n 个字符长,这是一种自我记录的形式。但是,如果您认真对待 3 字符格式(例如ISO-Alpha-3国家代码而不是ISO-Alpha-2),您肯定不会定义一个约束来执行规则,而不是让开发人员看一眼一个char(3)数据类型并得出自己的结论?

CHAR在 Oracle 6 中引入,我敢肯定,ANSI 兼容性的原因。可能有潜在客户决定购买哪种数据库产品,并且ANSI 兼容性在他们的清单上(或过去曾经是),并且CHAR在 ANSI 标准中定义了空白填充,因此 Oracle 需要提供它。你不应该实际使用它。

于 2017-02-10T17:48:42.870 回答
21

显示差异的简单示例:

SELECT 
    '"'||CAST('abc' AS VARCHAR2(10))||'"', 
    '"'||CAST('abc' AS CHAR(10))||'"' 
FROM dual;


'"'||CAST('ABC'ASVARCHAR2(10))||'"' '"'||CAST('ABC'ASCHAR(10))||'"'
----------------------------------- -------------------------------
"abc"                               "abc       "                   
1 row selected.

CHAR 对于字符长度始终固定的表达式很有用,例如美国各州的邮政编码,例如 CA、NY、FL、TX

于 2013-12-06T07:57:00.853 回答
7

只是为了避免混淆很多错误信息。以下是有关差异的一些信息,包括性能

参考:https ://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:2668391900346844476

由于 char 只不过是一个 VARCHAR2 空白填充到最大长度 - 即下面的 X 和 Y 列之间的差异:

创建表 t ( x varchar2(30), y char(30) ); 插入 t (x,y) 值( rpad('a',' ',30), 'a' );

绝对没有,并且考虑到下面 X 和 Y 列之间的差异:

插入 t (x,y) 值 ('a','a')

是 X 消耗 3 个字节(空指示符,前导字节长度,'a' 1 个字节)和 Y 消耗 32 个字节(空指示符,前导字节长度,'a' 30 个字节)

嗯,varchar2 将在某种程度上“在性能方面具有优势”。char(30) 始终是 30 个字节,这对我们有帮助 - 对我们来说,它只是一个 varchar2,它是空白填充到最大长度的。它可以帮助我们处理 - ZERO、zilch、zippo。

每当你看到有人说“它快 50%”时,就是这样——没有例子,没有科学,没有事实,没有故事来支持它——只要对他们大笑,继续前进。

该页面上还有其他“虚构的东西”,例如:

“在 CHAR 中搜索速度更快,因为所有字符串都存储在 彼此之间的指定位置,系统不必 搜索字符串的结尾。而在 VARCHAR 中,系统必须 先找到字符串的结尾,然后再查找搜索。”

FALSE:char 只是 varchar2 填充的空白 - 我们不会将字符串“存储在彼此之间的指定位置”。我们确实搜索字符串的结尾——我们使用前导字节长度来解决问题。

于 2017-11-02T10:42:52.333 回答
4

CHAR类型有固定大小,所以如果你说它是 10 个字节,那么它总是在数据库中存储 10 个字节,无论你存储任何文本还是只空 10 个字节都没有关系

VARCHAR2的大小取决于您实际要在数据库中存储的字节数。您指定的数字只是可以存储的最大字节数(尽管最少 1 个字节)

在处理固定长度的字符串时应该使用 CHAR(您事先知道要存储的字符串的确切长度) - 数据库可以更好更快地使用它,因为它知道确切的长度

当您不知道存储字符串的确切长度时,您应该使用 VARCHAR2。

您将同时使用的情况可能是:

name VARCHAR2(255),
zip_code CHAR(5) --if your users have only 5 place zip codes
于 2013-12-06T06:58:23.367 回答
3

字符

CHAR 应该用于存储固定长度的字符串。字符串值将在存储到磁盘之前填充空格/空白。如果使用这种类型来存储可变长度的字符串,会浪费大量的磁盘空间。

VARCHAR2

VARCHAR2 用于存储可变长度的字符串。字符串值的长度将与值本身一起存储在磁盘上。

At what times we use both?

这一切都取决于您的要求。

于 2013-12-06T06:58:51.027 回答
1

当存储在数据库中时,varchar2 仅使用分配的空间。例如,如果您有一个 varchar2(1999) 并将 50 个字节放入表中,它将使用 52 个字节。

但是当存储在数据库中时,char 总是使用最大长度并且是空白填充的。例如,如果您有 char(1999) 并将 50 个字节放入表中,它将消耗 2000 个字节。

于 2020-06-23T14:50:45.947 回答
-2

CHAR用于存储固定长度的字符串。如果使用这种类型来存储可变长度的字符串,将会浪费大量的磁盘空间。

VARCHAR2用于存储可变长度的字符串。

我们什么时候同时使用两者?

这可能会有所不同,具体取决于您的要求。

编辑:-

让我们通过一个示例来理解这一点,如果您有一个大小为 10 的学生姓名列;snameCHAR(10)和 如果插入列值'RAMA',则在值的右侧插入6 个空格。如果这是一个 VARCHAR 列;snameVARCHAR2(10).然后 Varchar 将占用 10 个可能的空格中的 4 个,并释放接下来的 6 个用于其他用途。

于 2013-12-06T06:59:11.673 回答