MySQL学习笔记(9)-数据类型(列类型)

数据类型(列类型)

所谓的数据类型:对数据进行统一的分类,从系统的角度出发为了能够使用统一的方式进行管理:更好的利用有限的空间。

SQL中将数据类型分成了三大类:数值类型,字符串类型和时间日期类型。


数值型

数值型数据:都是数值

系统将数值型分为整数型和小数型。

整数型

存放整型数据:在SQL中因为更多要考虑如何节省磁盘空间所以系统将整型又细分成了5类:

Tinyint 迷你整型,使用一个字节存储,表示的状态最多位256种

Smallint 小则航行,使用2个字节存储,表示的状态最多位65536种

Mediumint:中整型,使用3个字节存储

Int :标准整型,使用4个字节存储

Bigint :大整型,使用8个字节存储


创建一张整型表

-- 创建整型表
create table my_int(
int_1 tinyint,
int_2 smallint,
int_3 int,
int_4 bigint
)charset utf8;

-- 插入数据
insert into my_int values (100,100,100,100); -- 有效数据
insert into my_int values('a','b','199','f');
-- 无效数据:类型限定
insert into my_int values(255,10000,100000,10000000);
-- 错误,超出范围

SQL中的数值类型全部都是默认有符号:分正负

有时候需要使用无符号数据:需要给数据类型限定:int unsigned;--  无符号:从0开始

-- 给表增加一个无符号类型
alter table my_int add int_5 tinyint unsigned; -- 无符号类型
desc my_int;

-- 插入数据
insert into my_int values(127,1000,10000,100000,255);

查看表结构的时候,发现每个字段的数据类型之后都会自带一个括号,里面有指定的数字


显示宽度:没有特别的含义,只是默认的告诉用户可以显示的形式而已:实际上用户是可以控制的,这种控制不会改变数据本身的大小。

desc my_int;
insert into my_int values (127,0,0,0,255,255);
select * from my_int;

显示宽度的意义:在于当数据不够显示宽度的时候,会自动让数据变成对应的显示宽度:通常需要搭配一个前导0来增加宽度,不改变值得大小:zerofill(零填充):零填充会导致数值自动变成无符号

alter table my_int add int_7 tinyint(2) zerofill; -- 显示宽度为2,零填充
desc my_int;

零填充+显示宽度得效果

insert into my_int values(1,1,1,1,1,1,1);
insert into my_int values(100,100,100,100,100,100,100);
select * from my_int;

零填充得意义(显示宽度):保证数据格式

小数型

小数型:带有小数点或者范围超出整型得数值类型

SQL中:将小数型细分成两种:浮点型和定点型

浮点型:小数点浮动,精度有限,而且会丢失精度

定点型:小数点固定,精度固定,不会丢失精度

浮点型

浮点型是一种精度型数据:因为超出指定范围后,会丢失精度(自动四舍五入)

浮点型:理论分为两种精度

    Float:单精度,占用4个字节存储数据,精度范围大概为7位左右

    Double:双精度,占用8个字节存储数据,精度范围大概15位左右


创建浮点数表:浮点得使用方式:直接float表示没有小数部分,float(M,D):M代表总长度,D代表小数部分长度,整数部分长度位M-D。

-- 浮点数表
create table my_float(
f1 float,
f2 float(10,2),  -- 10位在精度范围之外
f3 float(6,2)  -- 6位在精度范围之内
)charset utf8;
desc my_float;

插入数据:可以是直接小数,也可以是科学记数法

-- 插入数据
insert into my_float values(1000.10,1000.10,1000.10); -- 符合条件
insert into my_float values(1234567890,12345678.90,1234.56); -- 符合条件
insert into my_float values(3e38,3.01e7,1234.56);
insert into my_float values(9999999999,99999999.99,9999.99);-- 最大值

浮点型数据得插入:整型部分是不能超出长度的,但是小数部分可以超出长度(系统会自动四舍五入)

-- 超出长度插入数据
insert into my_float values (123456,1234.123456768,123.9876543); --小数部分ok
insert into my_float values(123456,1234.12,12345.56);--整数部分超出

结果:浮点数一定会进行四舍五入(超出精度范围):浮点数如果是因为系统进位导致整数部分超出指定的长度,那么系统也允许成立。


定点型

定点型:绝对的保证整数部分不会被四舍五入(不会丢失精度),小数部分有可能(理论小数部分也不会丢失精度)


创建定点数表:以浮点数作为对比

-- 创建定点数表
create table my_deciaml(
f1 float(10,2),
d1 decimal(10,2),
)charset utf8;
desc my_decimal;

插入数据:定点数的整数部分一定不能超出长度(进位不可以),小数部分的长度可以随意超出(系统自动四舍五入)

-- 插入数据
insert into my_decimal values(12345678.90,12345678.90); -- 有效数据
insert into my_decimal values(1234.123456,1234.1234356); -- 小数部分超出:ok
-- 查看警告
show warnings;

浮点数如果进位导致长度溢出没有问题,但是定点数不行

insert into my_decimal values(99999999.99,99999999.99); -- 没有问题
insert into my_decimal values(99999999.99,99999999.999); -- 进位超出范围

查看数据效果


时间日期类型

Datetime:时间日期,格式是YYYY-mm-dd HH:ii:ss,表示的范围是从1000到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):1901-2156


创建时间日期表

-- 创建时间日期表
create table my_date(
d1 datetime,
d2 date,
d3 time,
d4 timestamp,
d5 year
)charset utf8;
desc my_date;

插入数据:时间time可以是负数,而且可以是很大的负数,year可以使用2位数插入,也可以使用4位数

-- 插入数据
insert into my_date values('2018-6-6 12:55:32','2018-6-6','12:27:33','2018-6-6 11:51:08',2018);
insert into my_date values('2018-6-6 12:55:32','2018-6-6','-12:27:33','2018-6-6 11:51:08',2018);
insert into my_date values('2018-6-6 12:55:32','2018-6-6','-211:27:33','2018-6-6 11:51:08',2018);
insert into my_date values('2018-6-6 12:55:32','2018-6-6','-2 11:27:33','2018-6-6 11:51:08',2018);
-- year可以使用2位或者4位
insert into my_date values('2018-6-6 12:55:32','2018-6-6','11:27:33','2018-6-6 11:51:08',69);
insert into my_date values('2018-6-6 12:55:32','2018-6-6','11:27:33','2018-6-6 11:51:08',70);
select * from my_date;

Timestamp字段:只要当前所在的记录被更新,该字段一定会自动更新成当前时间

desc my_date;
select * from my_date;
-- timestamp:修改记录
update my_date set d1 = '2018-6-6 14:17:22' where d5 = 2069;
select * from my_date;

字符串类型

定长字符串

定长字符串:char,磁盘(二维表)在定义结构的时候,就已经确定了最终数据的存储长度。

char(L):L代表length,可以存储的长度,单位为字符,最大长度值可以为255.

char(4):在utf8环境下,需要4*3 = 12个字节

变长字符串

变长字符串:varchar,在分配空间的时候,按照最大的空间分配:但是实际上最终用了多少,是根据具体的数据来确定。

varchar(L):L表示字符长度,理论长度是65536个字符,但是会多出1到2个字节来确定存储的实际长度

varchar(10) : 的确存了10个汉字,utf8环境下,10*3 + 1 = 31(bytes)

                    存储了3个汉字:3*3 +1 = 10(bytes)

定长与变长的存储实际空间(UTF8)

 实际存储数据 char(4) varchar(4) char占用字节 varcahr(占用字节)
ABCD ABCD ABCD 4*3=12 4*3+1=13
A A A 4*3=12 1*3+1=4
ABCDE x x 数据超过长度 数据超过长度

如何选择定长或者是变长字符串呢?

定长的磁盘空间比较浪费,但是效率高:如果数据基本上确定长度都一样,就是使用定长,如身份证,电话号码,手机号码等

变长的磁盘空间比较节省,但是效率低:如果数据不能确定长度(不同数据有变化),如姓名,地址等

文本字符串

如果数据量非常大,通常说超过255个字符就会使用文本字符串

文本字符串根据存储的数据的格式进行分类:text和blob

    Text:存储文字(二进制数据实际上都是存储路径)

    Blob:存储二进制数据(通常不用)

枚举字符串

枚举:enum,事先将所有可能出现的结果都设计好,实际上存储的数据必须是规定好的数据中的一个。

枚举的使用方式

    定义:enum(可能出现的元素列表);//如enum('男','女','不男不女','保密');

    使用:存储数据,只能存储上面定义好的数据

创建枚举表

-- 创建枚举表
create table my_enum(
gender enum('男','女','保密')
)charset utf8;
desc my_enum;

加入数据:作用之一:规范数据格式:数据只能是规定的数据中的其中一个

-- 插入数据
insert into my_enum values('男'),('保密'); -- 有效数据
-- 错误数据
insert into my_enum values('male'); -- 错误:没有该元素

作用之二:节省存储空间(枚举通常有一个别名:单选框):枚举实际存储的是数值而不是字符串本身。

在mysql中系统也是自动转换数据格式的:而且基本与PHP一样(尤其是字符串转数字)

证明字段存储的数据是数值:将数据取出来+0就可以判断出原来的数据存的到底是字符串还是数值:如果是字符串最终结果永远为0.

-- 将字段结果取出来进行+0运算
select * from my_enum;
select gender+0 ,gender from my_enum;

找出了枚举元素的实际规律:按照元素出现的顺序,从1开始编号


枚举原理:枚举在进行数据规范的时候(定义的时候),系统会自动建立一个数字与枚举元素对应关系(关系放到日志中):然后在进行数据插入的时候,系统自动将字符转换成对应的数字存储,然后在进行数据提取的时候,系统自动将数值转换成对应的字符串显示。

因为枚举实际存储的是数值,所以可以直接插入数值。

-- 数值插入枚举元素
insert into my_enum values (1),(2);
-- 将字段结果取出来进行+0运算
select gender+0 ,gender from my_enum;

集合字符串

集合跟枚举类似:实际存储的是数值,而不是字符串(集合是多选)

集合使用方式:

    定义:Set(元素列表)

    使用:可以使用元素列表中的元素(多个),使用逗号分隔

创建集合表

-- 创建集合表
create table my_set(
hobby set ('篮球','足球','乒乓球','羽毛球','排球','台球','网球','棒球')
)charset utf8;
desc my_set;


插入数据:可以使用多个元素字符串组合,也可以直接插入数值

-- 插入数据
insert into my_set values('足球,台球,网球');
insert into my_set values(3);

查看数据:数值+数据查看

-- 查看集合数据
select hobby+0 hobby from my_set;

集合中每一个元素都是对应一个对应的二进制位


集合的强大在于能够规范数据和节省空间。

Mysql记录长度

Mysql中规定:任何一个记录最长不能超过65535个字节。(varchar永远达不到理论值)

varchar的实际存储长度能达到多少呢?看字符集编码。

utf8下varchar的实际顶配

GBK下的varchar的实际顶配

-- 求出varchar在utf8和gbk下的实际最大长度
create table my_utf8(
name varchar(21844) -- 21844*3+2 = 65532+2=65534
)charset utf8;
create table my_gbk(
name varchar(32766) -- 32766*2+2=65532+2=65534
)charset gbk;

utf8下varchar的实际顶配:21844字符

gbk下varchar的实际顶配: 32766字符

效用完整的65535个字节长度:增加一个tinyint字段即可

create table my_utf81(
age tinyint,
name varchar(21844) -- 21844*3+2=65532+2=65534
)charset utf8;
create table my_gbk1(
age tinyint,
name varchar(32766) -- 32766*2+2=65532+2=65534
)charset gbk;

Mysql记录中,如果有任何一个字段允许为空,那么系统会自动从整个记录中保留一个字节来存储NULL(若想释放NULL所占用的字节:必须保证所有的字段都不允许为空)


-- 释放NULL
create table my_utf81(
age tinyint not null,
name varchar(21844) not null-- 21844*3+2=65532+2=65534
)charset utf8;
create table my_gbk1(
age tinyint not null,
name varchar(32766) not null -- 32766*2+2=65532+2=65534
)charset gbk;

Mysql中text文本字符串,不占用记录长度:额外存储。但是text文本字符串也是属于记录的一部分:一定需要占据记录中的部分长度:10个字节(保存数据的地址以及长度)。

-- text占用十个字节长度
create table my_text(
name varchar(21841) not null, -- 21841*3+2=65523+2=65525
content text not null -- 10
)charset utf8;

                                                                                                                                                    

猜你喜欢

转载自blog.csdn.net/qq_38826019/article/details/80591009