CHAR 还是 VARCHAR? 这是个问题!

数据库 MySQL
今天我们来对比下 ORACLE 与 MYSQL 中不同字符数据类型的异同,以避免因前期数据结构设计时数据类型选用不当,造成后续存储加工和处理数据时的各种坑。

 [[427024]]

本文转载自微信公众号「明哥的IT随笔」,作者 IT明哥 。转载本文请联系明哥的IT随笔公众号。

1 前言

大家好,我是明哥!

今天我们来对比下 ORACLE 与 MYSQL 中不同字符数据类型的异同,以避免因前期数据结构设计时数据类型选用不当,造成后续存储加工和处理数据时的各种坑。

2 ORACLE 与 MYSQL 中字符数据类型都有哪些

ORACLE 中内置的字符数据类型主要有以下三大类:

  • CHAR/NCHAR:存储固定长度的字符串,其中NCHAR使用 national character set;
  • VARCHAR2/VARCHAR/NVARCHAR2:存储变长字符串,其中 VARCHAR 等同于 VARCHAR2,NVARCHAR2 使用 national character set;
  • CLOB/NCLOB:存储大小可达 4GB 的字符串,其中 NCLOB 使用 national character set;

MYSQL 中字符数据类型主要有:

  • CHAR:存储固定长度的字符串;
  • VARCHAR:存储变长字符串
  • BLOB/TEXT:主要用来存储大的字符串。

可以看到:

  • 二者都有专门用来处理较大字符串的数据类型,如 CLOB/BLOB/TEXT;
  • 二者都有处理定长字符串的数据类型,如 CHAR;
  • 二者都有处理变长字符串的数据类型,如 VARCHAR;

以下我们重点对比下二者对定长和变长字段类型,即 CHAR 和 VARCHAR ,处理时的异同。

3 ORACLE 和 MYSQL 对 CHAR 和 VARCHAR 处理的相同点在哪里?

3.1 ORACLE 和 MYSQL 对定长字段类型 CHAR 的存储处理类似,都会对用户传入的实际的字符串进行加工处理后再存储:

  • 如果用户传入的实际的字符串的长度,跟 DDL 语句中声明的该 CHAR 字段的长度相等,则直接存储用户传入的值;
  • 如果用户传入的实际的字符串的长度,小于 DDL 语句中声明的该 CHAR 字段的长度,ORACLE 和 MYSQL 都会在字段末尾补充空格(blank-pad),直到达到声明的长度;
  • 如果用户传入的实际的字符串的长度,大于 DDL 语句中声明的该 CHAR 字段的长度,ORACLE 和 MYSQL 都会报错退出(注意:MYSQL中,可以配置使用非 STRICT SQL MODE,此时会截断超常字段然后存储截断后的值并告警,但不会报错退出);

3.2 ORACLE 和 MYSQL 对变长字段类型 VARCHAR 的存储处理类似,都不会对用户传入的实际的字符串进行加工处理,而是直接校验存储:

-如果用户传入的实际的字符串的长度,小于或等于 DDL 语句中声明的该 VARCHAR 字段的最大长度,则直接存储用户传入的值;(实际存储的数据,都是字段值的实际长度和字段的具体值);

  • 如果用户传入的实际的字符串的长度,大于 DDL 语句中声明的该 VARCHAR 字段的最大长度,ORACLE 和 MYSQL 都会报错(注意:MYSQL中,是报错还是截断,跟超长字段是正常字段还是 trailing spaces,以及是否是 STRICT SQL MODE 有关);

3.3 ORACLE 和 MYSQL 对变长字段类型 VARCHAR 的取出处理类似

  • ORACLE 和 MYSQL 对变长字段类型 VARCHAR 的取出处理类似,都不会对实际存储的字段值做加工处理,而是直接返回,因为存储时已经做了校验和加工。

3.4 ORACLE 和 MYSQL 中都是 VARCHAR(ORACLE 中是 VARCHAR2)的存储空间使用率更好

  • ORACLE 和 MYSQL 中都是 VARCHAR(ORACLE 中是 VARCHAR2)的存储空间使用率更好,因为 CHAR 类型字段在实际长度不够时会在末尾补充空格(blank-pads)并存储这些 trailing blanks 而 VARCHAR 不会,所以 VARCHAR 可以更有效地存储数据,空间使用率更高。

4 ORACLE 和 MYSQL 对 CHAR 和 VARCHAR 处理的不同点在哪里?

4.1 ORACLE 和 MYSQL 对 CHAR 和 VARCHAR 处理的不同点,体现在如何取出 CHAR 类型的字段数据上:

  • ORACLE 会将存储的值原封不动地取出,不做任何加工,所以通过LENGTH()函数返回的,就是 DDL 语句中声明的长度(当然底层存储时 pad 了 space);
  • MYSQL 会将存储的值最右边的空格全部截取后再取出,所以通过LENGTH()函数返回的,不是 DDL 语句中声明的长度,而是字段的实际有效长度(当然底层存储时 pad 了 space);

4.2 ORACLE 和 MYSQL 对 CHAR 和 VARCHAR 处理的不同点,体现在如何对比 CHAR 和 VARCHAR 类型的字段数据上:

  • Oracle 对 CHAR/NCHAR 采用的是 “blank-padded comparison semantics” 模式:如果对比的字段长度不同, Oracle 会在较短字段的末尾补充空格使得两者长度相同,然后再逐个字符进行比较。所以只有末尾空格数有差异的字段,对被认为是相等的字段;
  • Oracle 对 VARCHAR2/NVARCHAR2 采取的是 “non-padded comparison semantics” 模式:只有两个字段的长度相同且字符完全相同,才会被认为是相等的字段;
  • MySQL 对 CHAR, VARCHAR, 和 TEXT 采取的都是类似 ORACLE 的 “blank-padded comparison semantics” 的模式:即如果对比的字段长度不同, Oracle 会在较短字段的末尾补充空格使得两者长度相同,然后再逐个字符进行比较。所以只有末尾空格数有差异的字段,对被认为是相等的字段;

5 知识总结

  • ORACLE 和 MYSQL 都有对应变长字符串的数据类型,如 VARCHAR/VARCHAR2, 两者在数据的存储和取出上的处理类似;
  • ORACLE 和 MYSQL 都有对应定长字符串的数据类型,如 CHAR,两者对 CHAR 类型字段的存储处理类似,都会校验字段长度,并在字段不够时通过空格右补齐;
  • ORACLE 在取出 CHAR 类型字段时,不会做额外处理,会将存储的字段值直接取出;MYSQL 在取出 CHAR 类型字段时,会对存储的字段值做额外处理,会将字段最右端的空格截掉再返回;
  • Oracle 在对比 CHAR/NCHAR 类型字段时,采用的是 “blank-padded comparison semantics” 模式;
  • Oracle 在对比 VARCHAR2/NVARCHAR2 类型字段时,采取的是 “non-padded comparison semantics” 模式;
  • MySQL 在对比 CHAR, VARCHAR, 和 TEXT 类型字段时,采取的都是类似 ORACLE 的 “blank-padded comparison semantics” 的模式;

CHAR and varchar in mysql

CHAR in oracle and mysql

责任编辑:武晓燕 来源: 明哥的IT随笔
相关推荐

2015-05-05 09:39:57

编程被编程

2020-02-17 21:17:40

www域名主机

2020-06-21 05:55:45

勒索软件攻击赎金

2017-06-02 08:48:29

互斥锁JavaCAS

2018-05-29 09:08:16

vSAN 块存储应用

2011-09-01 14:22:06

OracleCharVarChar

2020-01-20 14:44:03

云计算架构IT

2012-09-13 10:44:32

Web设计Web分页架构设计

2017-04-25 14:58:02

网络可见性漏洞

2023-03-29 10:48:28

2018-03-05 08:52:57

2011-04-27 09:25:13

MySQL字符型数据

2010-11-26 13:18:53

MySQL字符串

2009-11-24 14:21:17

2024-03-18 08:11:27

jQuery 4.0前端开发web开发

2020-11-09 09:52:11

程序数据

2020-07-10 09:56:01

Java参数变量

2016-03-11 09:46:26

面向对象设计无状态类

2010-07-05 11:20:53

2010-07-28 13:50:14

点赞
收藏

51CTO技术栈公众号