数据库助教工作需要讲解MySQL基本数据类型,以下为准备内容
当我们学习一门程序语言时,首先可能是了解它的语法,接着就是学习它的数据类型了。而对于SQL这种用在以存储为主的数据库上的语言来说,了解它所支持的数据类型就更加重要了,而接下来我们就来学习一下MySQL数据表中支持的数据类型。
整数类型
整数类型由小到大可以分为tinyint、smallint、mediumint、int、bigint几类,默认表示有符号数。如果希望表示无符号数,可用关键字“unsigned”进行修饰。如:1 | score tinyint unsigned |
小数类型
小数类型可以分为精确小数类型(decimal)和浮点数类型(单精度float、双精度double)。
decimal(length,precision)用来表示精读确定的小数类型,其中length表示包括整数部分和小数部分的最大位数,precision表示精度(小数部分的位数)。其本质上是使用字符串来表示小数,因此数据库中存储的值就等于插入的值,不会像浮点数类型那样可能产生精读的丢失。
decimal(5,2)表示小数的取值范围:-999.99 ~ 999.99 decimal(5,0)表示:-99999 ~ 99999的整数 值得注意的是,如果插入的数据小数部分超过精读限制会进行四舍五入截断,而整数部分超出限制的话会报错。
浮点数类型的字节数和取值范围如下表所示,其也可以使用decimal的表示方式,且由于存储时十进制向二进制转化的缘故,可能存在精读的丢失。至于为什么表示范围是这么大,可以去了解一下浮点数阶码和位数的表示方式。
字符串类型
字符串类型主要可以分为定长字符串类型char和变长字符串类型varchar和text,在数据外观上使用单引号括起来以区别其他数据类型。
char(n)和varchar(n)在存储或检索过程中不进行大小写转换,检索时对大小写是不敏感的。这和表命名的问题是类似的,之所以使用下划线而不是驼峰命名法,是因为是否区分大小写是与操作系统有关的,Linux下默认区分大小写,而windows下不区分,所以使用驼峰命名会带来一些问题。
char(n)的n最大为255,也就是最多能存储255个字符。 varchar(n)的n取值实际上是受限于MySQL一行数据的最大长度以及字符编码方式。MySQL规定一行数据不能超过64K,所以varchar的长度不能超过65535字节,减去1个字节表示是否为NULL,2个字节存储字符串长度,剩下65532字节存储实际字符串。对于gbk编码来说,一个字符最多占2个字节,因此n最大为65532/2;对于utf-8编码,一个字符最多占3个字节,n最大为65532/3。
这里有必要说一下字符的编码方式问题。我们一般常说的Unicode码实际上是一个字符集。因为ASCII码最初设计的时候只使用1个字节表示英文字母和一些可打印字符等,在互联网普及的今天已经完全不够用。因此出现Unicode码来表示多国语言的字符和一些扩充符号,它使用两个字节表示基础的一些符号,包括不同国家语言常用的符号,也就是UCS-2。之后使用4个字节扩展了许多其他的符号,也就是UCS-4(目前只使用了3个字节)。而gbk、utf-8、utf-16这些是对Unicode的不同编码方式,gbk主要是对简体中文的编码方式,采用两个字节表示中文的Unicode码点;utf-8使用变长编码,1个字节表示英文字符,3个字节表示中文字符,对于英文的存储来说可以有效地节省存储空间;utf-16则是直接使用两个字节(大端或小端)来表示Unicode码点,与UCS-2对应,windows操作系统中所说的Unicode编码实际上就是指utf-16小端编码。
varchar(255)如果使用gbk编码存储一个'中'字,那么varchar(255)只占用3字节,其中2个字节存储字符'中',一个字节记录长度。 char(255)就算只存储一个汉字也需要占用255个字符长度的存储空间。
在插入尾部有空格的字符串的时候,char会将尾部空格去除,而varchar则不会。实际上char未填满的字符空间都会用空格填充,因此字符串尾部的空格无法被识别。MySQL中两种类型比较的时候会使用PADSPACE校对规则,忽略字段末尾的空格字符,如果希望区分需要用到length函数。
总结一下,以下情况使用varchar比较合适:
- 字符串列的最大长度比平均长度大很多
- 列的更新次数少,碎片不成问题
- UTF-8这样复杂的变长编码,使用不同的字节数存储字符
以下情况使用char合适:
- 字符串非常短或者所有值都接近一个长度,如MD5
- 经常变更的值,定长的char不容易产生碎片
- 列非常短,char存储效率更高,如存储字符'Y'或'N'表示布尔类型
另外如果是存储中文的话可以使用nvarchar(n),它是使用Unicode编码(UTF-16),可以在不同的系统中都很好的显示。
日期类型
date表示日期,默认格式为'YYYY-MM-DD',在MySQL中分隔符可任意指定,如@、%;time表示时间,格式'HH:MM:SS',其中分隔符必须为':';year表示年份datetime与timestamp是是日期与时间的混合类型,格式为'YYYY-MM-DD HH:MM:SS',该类型理论上可以使用date加time代替。这些类型可以使用字符串或者数字进行赋值,如果要获取当前时间,可以使用函数now()。
datetime(8字节)和timestamp(4字节)都是日期和时间的混合类型,他们的区别在于:
- datetime保存的时间范围较大,年的数字在1000 - 9999之间,timestamp保存的时间范围较小,年的数字在1970 - 2037之间
- NULL在插入timestamp字段后,实际的值是MySQL服务器当前的日期和时间,而在datetime中就是NULL
- 同一个timestamp类型的日期或时间,在不同的时区显示的结果不同
复合类型
MySQL 支持两种复合数据类型:enum枚举类型和set集合类型。enum类型的字段类似于单选按钮的功能,一个enum类型的数据最多可以包含65535个元素(1或2个字节)。set 类型的字段类似于复选框的功能,一个set类型的数据最多可以包含64个元素(1、2、4或8个字节)。
enum和set实际是采用整数存储,编号从1开始,0表示无效的enum值。
二进制类型
前面介绍的都是一些有实际意义的数据类型,但有一些数据是单纯地由'0','1'组成的字符串,比如说视频、音频和可执行程序等,这些数据就需要用二进制类型来存储。它与字符串类型的不同在于:字符串是以字符为单位存储,通过特定的编码将二进制串解释为字符,而二进制类型是按字节为单位存储,存储处理最原始的字节数据。
二进制类型可以类比字符串类型,主要有:binary、varbinary、bit、blob。其中blob用于存储二进制大对象,排序索引使用前max_short_length个字符,默认为1024K,可自行设置。可存储的最大值由类型确定,客户端和服务器之间可传递的最大值由内存和通信缓存区大小max_allowd_packet确定。
数据类型选择原则
对于数据库设计来说,选择合适的数据类型,不仅可以节省储存空间,还可以有效地提升数据的计算性能。 通常遵循以下原则:
- 越小越好:在符合应用要求(取值范围、精度)的前提下,尽量使用“短”数据类型
- 简单就好:数据类型越简单越好
- 在MySQL中,应该用内置的日期和时间数据类型,而不是用字符串来存储日期和时间
- 尽量采用精确小数类型(例如decimal),而不采用浮点数类型
- 尽量避免NULL字段,建议将字段指定为NOT NULL约束
- 整型是最好的选择,位数据类型可以用整数代替