Varchar2和Char之间的主要区别是什么?

28

创建表格:

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

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

结果:

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

请告诉我Varchar2和Char之间的区别是什么?在什么时候我们使用它们?

7个回答

32
虽然已经有几个正确描述 char 行为的答案,但我认为需要指出:除了三种特定情况之外,你不应该使用它

  1. 你正在创建一个固定长度的文件或报告,并且将非空值分配给 char 可以避免编写 rpad() 表达式。例如,如果 firstnamelastname 都被定义为 char(20),那么 firstname||lastname 是编写 rpad(firstname,20)||rpad(lastname,20) 的简洁方式,用于创建
    Chuck Norris
  2. 你需要区分显式空字符串 ''null。在 Oracle 中,通常它们是相同的,但是将 '' 分配给 char 值将触发其空白填充行为,而 null 不会,因此,如果很重要区分它们(我真的想不到理由),那么你有一种方法可以做到。
  3. 你的代码从其他系统移植过来(或者需要与之兼容),这些系统由于历史原因需要进行空白填充。在这种情况下,你被限制使用它,我很同情你。

实际上没有任何理由仅仅因为某些长度是固定的(例如 Y/N 标志或 ISO 货币代码如 'USD')而使用 char。它不会更有效率,也不会节省空间(varchar2 没有神话中的长度指示符,只有 char 的填充开销),也不会阻止任何人输入较短的值。(如果在 char(3) 货币列中键入 'ZZ',它将存储为 '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需要提供它。你不应该真正使用它。

7
这应该是最好的答案 - 特别是对于“你不应该真正使用它”! - Tony Andrews
3
+1,因为你的解释与Tom Kyte在asktom.oracle.com上发布的一些帖子相吻合:Char Vs Varchar是否应使用char或varchar2 - Mariano Desanze

22

一个简单的例子来展示它们之间的区别:

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。


3
CHAR并不真正“有用”:美国州代码与VARCHAR2一样可以有效地存储。 - Tony Andrews

7
为避免混淆,以下是一些关于性能差异的信息:
参考:https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:2668391900346844476 由于 char 只不过是一个空格填充至最大长度的 VARCHAR2,因此下面 X 和 Y 列之间的差异:
create table t ( x varchar2(30), y char(30) ); insert into t (x,y) values ( rpad('a',' ',30), 'a' );
就是绝对没有区别。并且,下面 X 和 Y 列之间的差异:
insert into t (x,y) values ('a','a')
在这里,X 占用 3 个字节(null 指示器、前导字节长度、一个字节的 'a'),而 Y 占用 32 个字节(null 指示器、前导字节长度、30 个字节的 'a ')。嗯,VARCHAR2 在性能上会稍微占优。当你看到有人说 "它比 char 快 50%" 的时候,只是这样 —— 没有例子、没有科学、没有事实、没有支持它的故事,就笑一笑然后继续前进。那个页面上还有其他 "捏造的事情",例如:
“在 CHAR 中搜索速度更快,因为所有字符串都存储在相互指定的位置上,系统不需要搜索字符串的结尾。而在 VARCHAR 中,系统必须首先找到字符串的结尾,然后再进行搜索。”
错误:char 只是一个空格填充的 varchar2,我们不会把字符串 "存储在相互指定的位置上"。我们确实搜索字符串的结尾 - 我们使用前导字节长度来解决问题。

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

在两者中哪个更好用? - ram12393
3
我认为在不了解需求的情况下,没有人可以说哪一个更好,因为根据具体需求,其中一个可能比另一个更好! - Rahul Tripathi

4

CHAR

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

VARCHAR2

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

And

At what times we use both?

这完全取决于您的需求。

1

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

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


-2

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

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

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

这可能会因您的需求而异。

编辑:

让我们通过一个例子来理解,如果您有一个大小为10的学生姓名列;sname CHAR(10),并且插入了一个列值'RAMA',则6个空格将插入到该值的右侧。如果这是一个VARCHAR列;sname VARCHAR2(10)。那么Varchar将占用10个可能中的4个空格,并释放下一个6个供其他用途。


我们在什么情况下通常会同时使用两者? - ram12393
1
@ram:让我们通过一个例子来理解,如果你有一个大小为10的学生姓名列;sname CHAR(10),如果插入一个列值“RAMA”,则会在该值右侧插入6个空格。如果这是一个VARCHAR列;sname VARCHAR2(10),那么Varchar将占用10个可能的空间中的4个,并释放下一个6个供其他用途。 - Rahul Tripathi
6在其他用途中是什么意思? - ram12393
@ram:- 6 对于其他用途意味着剩余的内存可以被某些其他值利用 :) - Rahul Tripathi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接