数据类型(列类型)
所谓的数据类型:对数据进行统一的分类,从系统的角度出发为了能够使用统一的方式进行管理,更好的利用有限的空间。
SQL中将数据类型分成了三大类:数值类型、字符类型和日期时间类型。
数值型
系统将数值型分为整数型和小数型
整数型
在SQL中因为更多要考虑如何节省磁盘空间,所以系统将整型又细分成5类:
- Tinyint:迷你整型,使用1个字节存储
- Smallint:小整型,使用2个字节存储
- Mediumint:中整型,使用3个字节存储
- Int:标准整型,使用4个字节存储
- Bigint:大整型,使用8个字节存储
创建一张整型表
插入数据:只能插入范围内的整型
SQL中的数值类型全部都是默认有符号:分正负
所有有时候需要使用无符号数据:需要给数据类型限定:int unsigned;(无符号,从0开始)
-- 给表增加一个无符号类型
alter table my_int add int_5 tinyint unsigned;
显示宽度:没有特别的含义,只是默认的告诉用户可以显示的形式而已,实际上用户是可以控制的,这种控制不会改变数据本身的大小
-- 插入一个规定显示宽度的字段,指定宽度为1
alter table my_int add int_6 tinyint(1) unsinged;
显示宽度的意义:在于当数据不够显示宽度的时候,会自动让数据变成对应的显示宽度,通常需要搭配一个前导0来增加宽度,不改变值大小:zerofill(零填充);零填充会导致数值自动变成无符号
-- 增加一个字段,显示宽度为2,0填充
alter table my_int add int_7 tinyint(2) zerofill;
零填充的意义:保证数据格式。
小数型
小数型:带有小数点或者超出整型的数值类型
SQL中,将小数型细分为两种:浮点型和定点型
- 浮点型:小数点浮动,精度有限,而且会丢失精度。
- 定点型:小数点固定,精度固定,不会丢失精度。
1.浮点型
浮点型数据就是一种精度型数据,因为超出指定范围之后,会丢失精度(自动四舍五入)
浮点型:理论上分为两种精度
- Float:单精度,占用4个字节存储数据,精度范围大概为7位左右
- Double:双精度,占用8个字节存储数据,精度范围大概为15位左右。
创建浮点表:浮点的使用方式,直接float表示没有小数部分,float(M,D):M代表总长度,D代表小数部分长度,整数部分长度为M-D。
插入数据:可以是直接小数,也可以是科学计数法。
浮点型数据的插入:整数部分是不能超出长度的,但是小数部分可以超出长度(系统会自动四舍五入)。
查看数据结果:浮点数一定会进行四舍五入(超出精度范围),浮点数如果是因为系统进位导致整数部分超出指定的长度,那么系统也允许成立。
2.定点型
定点型:绝对的保证整数部分不会被四舍五入(不会丢失精度),小数部分有可能(理论上小数部分也不会丢失精度)
创建定点数表
插入数据:定点数的整数部分一定不能超出长度(进位不可以),小数部分的长度可以随意超出(系统自动四舍五入)。
注意:浮点数如果进位导致长度溢出没有问题,但是定点数不行。
日期时间型
Datetime:时间日期,格式是YYYY-mm-dd HH:ii:ss,表示的范围是从10000到9999年,有0值:0000-00-00 00:00:00
Date:日期,就是datetime中的date部分
Time:时间(段),指定的某个区间之间,-时间到+时间
Timestamp:时间戳,并不是时间戳,只是从1970年开始的YYYY-mm-dd HH:ii:ss格式与datetime完全一致
Year:年份,有两种形式,year(2)和year(4)
创建时间表
插入数据:时间time可以是负数,而且可以是很大的负数,year可以使用2位数插入,也可以使用4位数
Timestamp字段:只要当前所在的记录被更新,该字段一定会自动更新成当前时间。
网站是以PHP为实现的主要操作对象:PHP中有非常强大的时间日期处理函数:date,只需要一个时间戳就可以转换成任意类型的时间,以PHP为主的时候,都是在数据库使用时间戳(整型)来存储时间。
字符串类型
在SQL中,将字符串类型分为6类:char,varchar,text,blob,enum和set。
定长字符串
定长字符串:char,磁盘(二维表)在定义结构的时候,就已经确定了最终数据的存储长度。
char(L):L代表length,可以存储的长度,单位为字符,最大长度可以为255.
char(4): 在UTF8环境下,需要4*3=12个字节。
变长字符串
变长字符串:varchar,在分配空间的时候,按照最大的空间分配,但是实际上最终用不了多少,是根据具体的数据来确定
varchar(L):L表示字符长度,理论上长度为65536个字符,但是会多出1到2个字节来确定存储的实际长度,255字符以下会多出1个,实际上长度超过255,既不用定长也不用变长,使用文本字符串text。
问:如何选择定长或者变长字符串呢?
答:定长的磁盘空间比较浪费,但是效率高;如果数据基本上确定长度都一样,就使用定长,如身份证号,电话号码,手机号码等。
变长的磁盘空间比较节省,但是效率低;如果数据不能确定长度(不同数据有变化),就使用变长,如姓名,地址等。
文本字符串
如果数据量非常大,通常说超过255个字符就会使用文本字符串。
文本字符串根据存储的数据的格式进行分类:text和blob
text:存储文字(二进制数据实际上都是存储路径)
blob:存储二进制数据(通常不用)
枚举字符串
枚举:enum,事先将所有可能的结果都设计好,实际上存储的数据必须是规定好的数据中的一个
-- 创建枚举表
create table my_enum(
gender enum('男', '女', '保密')
)charset utf8;
作用:
- 加入数据时,规范了数据格式,数据只能是规定的数据的其中一个。
- 节省存储空间(枚举通常有一个别名:单选框),枚举实际存储的是数值而不是字符串本身。
枚举元素的实际顺序:按照元素出现的顺序,从1开始编号。
枚举原理:枚举在进行数据规范的时候(定义时),系统会自动建立一个数字与枚举元素的对应关系(关系放到日志中),然后在进行数据插入时,系统自动将字符转换成对应的数字存储,然后再进行数据提取的时候,系统自动将数值转换成对应的字符串显示。
因为枚举实际存储的是数值,所以可以直接插入数值。
集合字符串
集合跟枚举很类似:实际存储的是数值,而不是字符串(集合是多选的)
集合使用方式:
定义:set(元素列表)
使用:可以使用元素列表中的多个元素,用逗号隔开。
-- 创建集合表
create table my_set(
hobby set('篮球', '足球', '乒乓球', '羽毛球', '排球', '台球', '网球', '棒球')
)charset utf8;
-- 插入多个元素
insert into my_set values('足球, 台球, 网球');
插入数据:可是使用多个元素字符串组合,也可以直接插入数值。
集合中,每一个元素都是对应一个二进制位,被选中为1,没有则为0,最后反过来。
select hobby + 0, hobby from my_set;
-- 会发现数据为'足球, 台球,网球'对应的数值为98,对应的二进制是1100010
集合中元素的顺序没有关系,最终系统都会去匹配顺序。
集合的强大在于能够规范数据和节省空间。
Mysql记录长度
Mysql中规定:任何一条记录最长不能超过65535个字节(而varchar最长是65536个字符,所以varchar永远达不到理论值)
varchar实际存储长度能达到多少呢?看字符集编码。
utf8下的varchar的实际最大值21844字符
21844 *
3 + 2 = 65534字节
gbk下的varchar的实际最大值32766字符
32766 *
2 + 2 = 65534字节
想要完整的65525个字节长度,增加一个tinyint字段
发现问题:太大了
因为Mysql记录中,如果有任何一个字段允许为空,那么系统会自动从整个记录中保留一个字节来存储NULL。
所以正确创建为:
create table my_utf8(
name varchar(21844) not null,
age tinyint no null
)charset utf8;
Mysql中text文本字符串, 不占用记录长度:额外存储,但是text文本字符串也是属于记录的一部分,一定需要占据记录中的部分长度:10个字节(保存数据的地址以及长度)。