MySQL和Oracle对char数据类型处理的不同之处

摘要:实例对比MySQL和Oracle对char数据类型处理的不同之处。

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却不会。

你更喜欢哪家的处理方式,为什么呢?

© 2020, morinson. 版权所有. 欢迎转载,但请保留作者及出处。