char在各种数据库中都被支持,用来存储较短的字符串,当然MySQL和Oracle也都有,但是却有一些不同之处,我们先来看个例子。
MySQL中,创建一个表,包含数据类型为char(4)的列c,并插入数据。
root@database-one 20:37: [(none)]> use gftest Database changed root@database-one 20:37: [gftest]> create table vc(v varchar(4),c char(4)); Query OK, 0 rows affected (0.19 sec) root@database-one 20:37: [gftest]> insert into vc values('ab ','ab '); Query OK, 1 row affected (0.01 sec) root@database-one 20:38: [gftest]> commit; Query OK, 0 rows affected (0.00 sec) root@database-one 20:38: [gftest]> select length(v),length(c) from vc; +-----------+-----------+ | length(v) | length(c) | +-----------+-----------+ | 4 | 2 | +-----------+-----------+ 1 row in set (2.45 sec)
复制
通过查询发现,char列插入的值是4个长度的字符串,但查询时,长度却是2。追加一个字符可以看得更清晰:
root@database-one 20:38: [gftest]> select concat(v,'+'),concat(c,'+') from vc; +---------------+---------------+ | concat(v,'+') | concat(c,'+') | +---------------+---------------+ | ab + | ab+ | +---------------+---------------+ 1 row in set (0.01 sec)
复制
char列最后的空格已经被删除。我们再插入一条记录看看:
root@database-one 20:39: [gftest]> insert into vc values('cd','cd'); Query OK, 1 row affected (0.01 sec) root@database-one 20:39: [gftest]> commit; Query OK, 0 rows affected (0.00 sec) root@database-one 20:39: [gftest]> select concat(v,'+'),concat(c,'+') from vc; +---------------+---------------+ | concat(v,'+') | concat(c,'+') | +---------------+---------------+ | ab + | ab+ | | cd+ | cd+ | +---------------+---------------+ 2 rows in set (3.15 sec)
复制
插入的’cd’,查询结果继续是’cd’。
同样的例子,我们在Oracle中看看效果:
SQL*Plus: Release 11.2.0.4.0 Production on Tue Feb 11 20:41:56 2020 Copyright (c) 1982, 2013, Oracle. All rights reserved. Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production With the Partitioning, OLAP, Data Mining and Real Application Testing options SQL> create table vc(v varchar(4),c char(4)); Table created. SQL> insert into vc values('ab ','ab '); 1 row created. SQL> commit; Commit complete. SQL> select length(v),length(c) from vc; LENGTH(V) LENGTH(C) ---------- ---------- 4 4 SQL> select concat(v,'+'),concat(c,'+') from vc; CONCAT(V,'+') CONCAT(C,'+') --------------- --------------- ab + ab +
复制
看到没有,char列插入的值是4个长度的字符串,查询时,长度继续是4,空格继续在。我们再插入一条记录看看:
SQL> insert into vc values('cd','cd'); 1 row created. SQL> commit; Commit complete. SQL> select concat(v,'+'),concat(c,'+') from vc; CONCAT(V,'+') CONCAT(C,'+') --------------- --------------- ab + ab + cd+ cd +
复制
插入的’cd’,查询结果多了2个空格。
为什么会这样呢?我们去官方文档中找找答案。
MySQL官方文档对其CHAR说明中有下面一段:
The length of a CHAR column is fixed to the length that you declare when you create the table. The length can be any value from 0 to 255. When CHAR values are stored, they are right-padded with spaces to the specified length. When CHAR values are retrieved, trailing spaces are removed unless the PAD_CHAR_TO_FULL_LENGTH SQL mode is enabled.
CHAR列的长度固定为创建表时声明的长度。长度可以是0到255之间的任意值。在存储CHAR值时,会用空格将其右填充到指定的长度。检索CHAR值时,除非启用PAD_CHAR_TO_FULL_LENGTH SQL模式,否则将删除尾随空格。
Oracle官方文档对其CHAR说明中有下面一段:
The CHAR data type specifies a fixed-length character string. Oracle ensures that all values stored in a CHAR column have the length specified by size. If you insert a value that is shorter than the column length, then Oracle blank-pads the value to column length. If you try to insert a value that is too long for the column, then Oracle returns an error.
CHAR数据类型指定固定长度的字符串。Oracle确保存储在CHAR列中的所有值都具有由size指定的长度。如果插入的值小于列长度,则Oracle blank将该值填充到列长度。如果您尝试插入的值对于列太长,则Oracle将返回一个错误。
至此,真相大白啦,原来MySQL和Oracle在存储char时,如果值长度不够,都会填充,区别在于检索(读取)时,MySQL默认(因为默认情况下PAD_CHAR_TO_FULL_LENGTH SQL模式不开启)会删除右侧空格,而Oracle却不会。
你更喜欢哪家的处理方式,为什么呢?