所谓的数据类型:对数据进行统一的分类,从系统的角度出发为了能够使用统一的方式进行管理,更好地利用有限空间。sql中将数据类型分成了3大类,分别是:数值类型、字符串类型和日期类型。
1、值类型。
数值型包括整数型和小数型。
1.1、整数型。
整数型用于存放整型数据,在Sql中因为更多地要考虑如何节省空间,系统将整型又细分为以下5类。
a)、tinyint:迷你整型。使用1个字节进行存储,表示的状态最多为256种(常用)。
b)、smallint:小整型。使用2个字节进行存储,表示的状态最多为256种(常用)。
c)、mediumint:中整型。使用3个字节存储。
d)、int:标准整型。使用4个字节存储(常用)。
e)、bigint:大整型。使用8个字节进行存储。
例子练习(引出去掉符号):
创建一个名叫【my_tinyint】表,为其添加一个age字段,为其指定为数据类型为tinyint。
Create table my_tinyint(
age tinyint
)charset utf8;
插入数据:insert into my_tinyint values(255),这个时候会报错。
错误原因是:超出范围,Sql中的数值类型默认全部是有符号的,分正负,tinyint(-128到127),如果使用无符号数据,需要去掉符号,去掉符号用 unsigned,如 age tinyint unsigned,无符号从0开始。
修改字段,为字段去掉符号。
alter table my_tinyint modify age tinyint unsigned;
再次插入数据:insert into my_tinyint values(255);
指定宽度:
查看表结构的时候,发现每个字段的数据类型之后都会带一个括号,括号里面有指定数字,里面的数字指的是宽度的意思,没有特别的含义,只是默认第告诉用户可以显示的形式而已,
实际上用户是可以控制的,这种控制不会改变数据本身的大小。
例子1:
创建一个名叫【my_tinyint1】的数据库,为其添加一个 score 字段,数据类型为tinyint,为其指定宽度为1。
Create table my_tinyint1(
score tinyint(1) unsigned
)charset utf8;
插入数据:insert into my_tinyint1 values (255); 这个时候插入的数据是255也不会报错(这种控制不会改变数据本身的大小)。
显示宽度的意义在于:当数据不够显示宽度的时候,会自动让数据变成对应的显示宽度(保证数据格式)。
如果给的是2位,插入的时候插入的是1位,要显示宽度为2位,通常需要搭配一个前导 0 来增加宽度,不改变值大小,用 zerofill 填充。零填充会导致数值自动变成无符号。
例子:创建1个名叫【my_tinyint2】的表,为其添加一个score字段,数据类型为tinyint,宽度为2,并添加 0 填充。
create table my_tinyint2(
score tinyint(2) zerofill
)charset utf8;
插入数据:insert into my_tinyint2 values(5);
1.2、小数型。
Sql中,将小数型又细分为两种,浮点型和定点型。
1.2.1)、浮点型:
小数点浮动,精度有限,而且不会丢失精度。
浮点型数据是一种精度型数据,因为超出指定范围之后,会丢失精度(自动四舍五入)。理论上又分为两种精度,分别是:
a)、float:单精度。占用4个字节存储数据,精度范围大概为7位左右。
height float:直接使用 float 表示没有小数部分。
money float(M,D):M 代表总长度,D代表小数部分长度。整数部分长度为 M-D。
浮点型数据的插入,整型部分是不能超出长度的,小数部分是可以超出长度(系统会自动四舍五入)。
例子:创建一张名叫【my_float1】的表,里面添加一个【money】字段,为其指定类型为float,其中整数部分为6,小数部分为5。
create table if not exists my_float1(
money float(11,5)
)charset utf8;
插入数据:
insert into my_float1 values (123456.12345); -- 小数点为5位小数(有效数据)
insert into my_float1 values (123456.123456); -- 小数点为6位小数(有效数据,小数点是可以超出指定长度,整数不可以)。
插入数据,将整数长度超过6。
insert into my_float1 values (1234567.123456); -- 小数点为6位小数(无效数据,整数部分布不能超过指定长度)。
但是有一种情况是可以超过指定长度的。浮点型一定会进行四舍五入的(超出精度范围),浮点数如果因为系统进位导致整数部分超出指定的长度,那么系统允许成立,
如果直接插入7位整数会报错。
insert into my_float1 values(999999.99);
1.2.2)、定点型:
小数点固定,精度固定,不会丢失精度。用 decimal 数据类型定义。
定点型会绝对的保证整数部分不会被四舍五入(不会丢失精度),小数部分有可能(理论小数部分也不会丢失精度,在自己的范围内不会进位,不在自己范围内会进位)。
插入数据时,定点数的整数部分一定不能超出长度(进位)不可以,小数部分的长度是可以随意超出指定长度的(系统会自动四舍五入)。
例子:创建1个名叫【my_decimal】的表,添加一个【money】字段,为其指定数据类型为decimal,且整数长度和小数长度都为5。
create table if not exists my_decimal(
money decimal(10,5)
)charset utf8;
插入数据:
insert into my_decimal values(66666.99999); -- 整数部分不会进位(有效数据)
直接插入长度大于5的数据会报错。
insert into my_decimal values(666666.99999); -- 整数部分不会进位(无效数据)。
那什么时候定点型数据,什么时候用浮点型数据呢?
如果数据非常精确,用定点,粗略大致算的时候就用浮点就行了。
2、字符串类型。
在Sql中,字符串类型分为6类,分别是:char、varchar、text、blob、enum和set。
a)、定长字符串 char。
char:磁盘(二维表)在定义结构的时候,就已经确定了最终数据的存储长度。
单位为字符,最大长度值为255。
char(4):在utf8环境下,需要 4 * 3 = 12个字节。
b)、变长字符串 varchar。
varchar 在分配空间的时候,按照最大的空间分配,但是实际上用了多少,是根据具体的情况来确定的。
varchar(L):L表示length(长度),理论长度是65536个字符,但是会多出 1 到 2 个字节来确定存储的实际长度,但是实际上如果长度超过255,既不用定长,也不用变长,使用文本字符串text。
varchar(10) :存了10个汉字,在utf8环境下,需要 (10 * 3) + 1 = 31(bytes)来存储。
定长与变长的实际存储空间(utf8环境下)
如何选择定长与变长的字符串呢?
定长的磁盘空间比较浪费,但是效率高,如果数据确定长度都一样,就会使用定长,如身份证号码、电话号码和手机号码。
变长的磁盘空间比较节省,但是效率低,如果数据不能确定长度(不同数据有变化),如姓名(有的人姓名为2个字,有的4个),家庭地址。
c)、文本字符串。
如果数据量非常大,通常说超过255个字符就会使用字符串。
文本字符串根据存储的数据格式进行分类,text和blob。
text:存储文字(二进制实际上都是存储路径)。
blob:存储二进制数据(通常不用)。
d)、枚举字符串。
枚举:enum,事先将所有可能出现的结果都设计好,实际存储的数据必须是定义好的数据中的其中一个。
枚举的作用:
规范数据格式,数据只能是规定的数据的其中之一。
节省存储空间(枚举通常有1个别名,单选框),枚举实际存储的是字符串本身。
语法: enum(可能出现的元素列表)。如 enum('男','女');
例子:创建一张【my_enum】表,添加一个 sex 字段,为其指定数据类型为enum。
create table if not exists my_enum(
sex enum('男','女','保密')
)charset utf8;
插入数据:insert into my_enum values('男');
在MySql中,系统也是自动转换数据格式的,而且基本与PHP一样(尤其是字符串转数字),证明字段存储的数据是数值,将数据取出来+0,就可以判断出原来的数据存的是字符串还是数值,如果是字符串,
最终结果永远是0,否则就是其他值,如select sex + 0 from my_enum;
编号是从 1 开始。
枚举原理:枚举在进行数据规范的时候(定义的时候),系统会自动建立一个与数字与枚举元素的对应关系(关系放到日志中),然后进行数据插入的时候,系统会自动将字符串转换成对应的数字存储,然后进行
数据提取的时候,系统自动将值转换成对应的字符串显示,如国家、省份。
枚举可以直接插入数值(再次证明存储的是数值)。
insert into my_enum values(1);
d)、集合字符串。
集合和枚举很类似,实际存储的是数值,而不是字符集(集合是多选)。
语法: 字段名 set(元素列表)
例子:创建1个名叫【my_set】的表,为其加入一个hobby字段,为其设置数据类型为集合。
create table my_set(
hobby set('足球','篮球','乒乓球')
)charset utf8;
插入数据:直接插入数值。
insert into my_set values(1);
insert into my_set values(3); 这个地方记住一下插入的3是足球篮球。
3、MySql记录长度。
MySql中规定,任何一条记录最长不能超过65535个字节(varchar永远达不到理论值)。
Varchar的实际长度能达到多少呢?
utf8环境下(3个字节存一个汉字),varchar的实际顶配为21844个字符。
gbk环境下(2个字节存1个汉字),varchar的实际顶配为32766字符。
测试1、utf8环境下。
创建1个【my_utf8】表,里面添加一个【name】字段,为【name】字段设置数据类型为varchar,指定宽度为65535个字节。
create table my_utf8(
name varchar(65535)
)charset utf8;
由于上图说,最大值只能是21845个字符,因此指定为65535报错,那么久设置最大值为21845个字符。
create table my_utf8(
name varchar(21845)
)charset utf8;
仍然是创建失败,那么接下来就分析一下。
(21845 * 3) + 2 = 65535 + 2 = 65537(bytes) -- 21845是最大值,utf8下是一个汉字占3个字节,+2(varchar要比实际空间多出1到2个字符出来)
因此最大只能是21844个字符,(21844 * 3) + 2 = 65532 + 2 = 65534(bytes)。
create table my_utf8(
name varchar(21844)
)charset utf8;
测试2、gbk环境下。
创建1个【my_utf8】表,里面添加一个【name】字段,为【name】字段设置数据类型为varchar,指定宽度为65535个字节。
create table my_gbk(
name varchar(65535)
)charset gbk;
由于上图说,最大值只能是21845个字符,因此指定为65535报错,那么久设置最大值为21845个字符。
create table my_gbk(
name varchar(32767)
)charset gbk;
仍然创建失败,接下来分析一下。
(32767 * 2 ) + 2 = 65534 + 2 = 65536(bytes) -- 超过最大字节范围。
因此最大只能为32766,(32766 * 2) + 2 = 65532 + 2 = 65534(bytes)
如果想要用完整个65535个字节长度。
如果想要使用完65535个字节,只需要再增加1个字段,为其指定类型为tinyint即可。
例子:
create table if not exists my_utf82(
age tinyint(1) unsigned,
name varchar(21844)
)charset utf8;
创建失败,失败原因:在mysql中,如果有1个字段允许为空,那么系统会自动从整个记录中保留1个字节来存储null(占用1个字节),若想要释放null所占用的字节,就必须保证所有的字段不允许为空。
create table if not exists my_utf82(
age tinyint(1) unsigned not null,
name varchar(21844) not null
)charset utf8;
End。