目录
一、MySQL数据类型分类
MySQL 数据类型可以大致分为以下三类:
- 数值类型:用于存储整数、小数、浮点数等数值数据。MySQL 支持所有标准 SQL 数值数据类型,包括 INTEGER、SMALLINT、DECIMAL、NUMERIC、FLOAT、REAL 和 DOUBLE PRECISION。此外,MySQL 还支持一些扩展的数值类型,如 TINYINT、MEDIUMINT、BIGINT 和 BIT。数值类型的选择要考虑存储范围、精度和空间效率等因素。
- 日期/时间类型:用于存储日期和时间值,如年份、日期、时间戳等。MySQL 支持的日期/时间类型有 YEAR、TIME、DATE、DATETIME 和 TIMESTAMP。日期/时间类型的选择要考虑存储格式、时区和自动更新等因素。
- 字符串类型:用于存储文本或二进制数据,如字符、文本、枚举等。MySQL 支持的字符串类型有 CHAR、VARCHAR、BINARY、VARBINARY、BLOB、TEXT、ENUM 和 SET。字符串类型的选择要考虑存储长度、字符集和排序规则等因素。
二、数值类型
1、整数类型
这里用MySQL的tinyint类型举例,来说明整数类型的用法
sql
mysql> create table tt1(num tinyint);
mysql> insert into tt1 values(1);
mysql> insert into tt1 values(128); //-- 越界插入,报错
mysql> select * from tt1;
说明 :
在 MySQL 中,整型可以指定是有符号的和无符号的,默认是有符号的。 可以通过UNSIGNED 来说明某个字段是无符号的。
sql
mysql> create table tt2(num tinyint unsigned);
mysql> insert into tt2 values(-1); //-- 无符号,范围是: 0 - 255
mysql> insert into tt2 values(255);
mysql> select * from tt2;
注意:使用有符号的和无符号是根据业务要求来选择的,没有哪种更好的说法。
2、bit类型
基本语法
sql
bit(M) : 位字段类型。M表示每个值的位数,范围从1到64。如果M被忽略,默认为1。
sql
mysql> create table tt4 ( id int, a bit(8));
mysql> insert into tt4 values(10, 10);
mysql> select * from tt4;
我们发现发现很怪异的现象,a的数据10没有出现,这是因为bit字段在显示时,是按照****ASCII码对应的值显示。
示例:
sql
mysql> insert into tt4 values(65, 65);
mysql> insert into tt4 values(65, 'A');
mysql> select * from tt4;
如果我们有这样的值,比如性别,只存放 0 或 1 ,这时可以定义 bit(1) 。这样可以节省空间。
sql
mysql> create table tt5(gender bit(1));
mysql> insert into tt5 values(0);
mysql> insert into tt5 values(1);
mysql> insert into tt5 values(2); //会发生越界
3、小数类型
1、float类型
sql
语法:float[(m, d)] [unsigned] : M指定数字位数总长度,d指定小数位数,占用空间4个字节
//m和n根据需求设置
(1)float(4,2) 表示的范围是 -99.99 ~ 99.99 , MySQL 在保存值时会进行四舍五入。
示例:
sql
mysql> create table tt6(id int, salary float(4,2));
mysql> insert into tt6 values(100, -99.99);
mysql> insert into tt6 values(101, -99.991); //多的这一点会四舍五入
mysql> select * from tt6;
四舍五入后如果数字超过范围,数据插入会失败。
(2)如果定义的是 float(4,2) unsigned 这时,因为把它指定为无符号的数,范围是 0 ~ 99.99
sql
create table tt7(id int, salary float(4,2) unsigned);
mysql> insert into tt7 values(100, -0.1);
mysql> insert into tt7 values(100, 99.99);
2、decimal类型
sql
语法:decimal(m, d) [unsigned] : 定点数m指定长度,d表示小数点的位数
decimal和float都是用来表示小数的数据类型,但它们有不同的特点和用途。
decimal是一种定点数,它用128位二进制来存储一个十进制数,可以保证小数的精度不会丢失,常用于金融运算或者要求高精度的场合。
示例:
sql
mysql> create table tt8 ( id int, salary float(10,8), salary2 decimal(10,8));
mysql> insert into tt8 values(100,23.12345612, 23.12345612);
mysql> select * from tt8;
建议:如果希望小数的精度高,推荐使用decimal。
三、字符串类型
1、char
sql
语法:char(L): 固定长度字符串,L是可以存储的长度,单位为字符,最大长度值可以为255
//这里的字符不是C或者C++的字符,而是一个符号,比如数字、字母或者汉字等等
sql
create table tt9(id int, name char(2));
mysql> insert into tt9 values(100, 'ab');
mysql> insert into tt9 values(101, '字符');
mysql> insert into tt9 values(101, '123');
char 最多只能放255个字符
2、varchar
sql
语法:varchar(L): 可变长度字符串,L表示字符长度,最大长度65535个字节
//注意这里是字节,不是字符
示例:
sql
mysql> create table tt10(id int ,name varchar(6)); //表示这里可以存放6个字符
mysql> insert into tt10 values(100, 'hello');
mysql> insert into tt10 values(100, '我爱你,中国');
mysql> select * from tt10;
关于 varchar(len), 这个 len 值,和表的编码密切相关
varchar字节 长度可以指定为 0 到 65535 之间的值,但是有 1 - 3 个字节用于记录数据大小,所以说有效字 节数是65532 。 当我们的表的编码是utf8 时, varchar(n) 的参数 n 最大值是 65532/3=21844[ 因为 utf中,一个字符占用3个字节 ] ,如果编码是 gbk , varchar(n) 的参数 n 最大是 65532/2=32766 (因为 gbk中,一个字符占用2 字节)。
sql
mysql> create table tt11(name varchar(21845))charset=utf8; //验证utf8确实是不
能超过21844
mysql> create table tt11(name varchar(21844)) charset=utf8;
我们再来新建一张表,这次我们在tt11的基础上加一个id列,结果我们发现失败了
sql
create table tt12(id int,name varchar(21844))charset=utf8;
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs
这条SQL语句会失败的原因是name字段的长度 超过了表的最大行长度 (max row size,65535 bytes)。根据MySQL的文档, 表的最大行长度是65535字节 ,不管使用什么存储引擎。而varchar(21844)类型的字段在utf8字符集下,每个字符最多占用3个字节,所以name字段最多占用65536字节,超出了限制。
可是就目前来看,varchar除了范围比char大一点,它们还有什么区别吗?我们接着往下看
3、char和varchar****比较
那么如何选择char和varchar呢?可以根据以下几点
如果数据确定长度都一样,就使用定长( char ),比如:身份证,手机号, md5
如果数据长度有变化 , 就使用变长 (varchar), 比如:名字,地址,但是你要保证最长的能存的进去。
定长的磁盘空间比较浪费,但是效率高。
变长的磁盘空间比较节省,但是效率低。
定长的意义是,直接开辟好对应的空间
变长的意义是,在不超过自定义范围的情况下,用多少,开辟多少。
四、日期和时间类型
常用的日期有如下三个:
date : 日期 'yyyy - mm - dd' ,占用三字节
datetime 时间日期格式 'yyyy - mm - dd HH:ii:ss' 表示范围从 1000 到 9999 ,占用八字节
timestamp :时间戳,从 1970 年开始的 yyyy - mm - dd HH:ii:ss 格式和 datetime 完全一致,占用四字节
案例:
sql
mysql> create table birthday (t1 date, t2 datetime, t3 timestamp);
mysql> insert into birthday(t1,t2) values('2001-12-07','2001-01-01 12:00:00');
mysql> select * from birthday;
注意:添加数据时,时间戳自动补
sql
mysql> update birthday set t1='1999-12-07';
mysql> select * from birthday;
更新数据,时间戳会更新
五、enum和set
enum(' 选项 1',' 选项 2',' 选项 3',...);
该设定只是提供了若干个选项的值,最终一个单元格中,实际只存储了其中一个值;而且出于效率考虑,这些值实际存储的是" 数字 " ,因为这些选项的每个选项值依次对应如下数字: 1,2,3,.... 最多 65535个;当我们添加枚举值时,也可以添加对应的数字编号。
set :集合, " 多选 " 类型;
set(' 选项值 1',' 选项值 2',' 选项值 3', ...);
该集合提供了若干个选项的值,最终一个单元格中,设计可存储了其中任意多个值;而且出于效率
考虑,这些值实际存储的是 " 数字 " ,因为这些选项的每个选项值依次对应如下数字: 1,2,4,8,16,32,.... 最多64个。
示例:
sql
mysql> create table votes(
-> name varchar(32),
-> gender enum('男','女'),
-> hobby set('游戏','动漫','音乐')
-> );
现在往表里添加数据,添加数据时可以直接写入选项,也可以用下标(enum)或者用位图(set)来表示。
sql
mysql> insert into votes values('kevin','男','游戏,音乐');
mysql> insert into votes values('kiana','2',3);
mysql> select*from votes;
可以发现,set的1,2,3......不是下标,而是要看成由01组成的位图,是1就表示选中。
查询数据示例:
sql
select*from votes where hobby='游戏';
但是这样只能查出爱好只是游戏的人,不能查询出所有的,游戏是其爱好的人。
所以我们需要学习: 集合查询 find_ in_ set 函数:
find_in_set函数的语法是:find_in_set(str, strlist),其中str是要查找的字符串,strlist是由逗号分隔的字符串列表。例如,find_in_set('b', 'a,b,c,d')返回2,因为'b'在'a,b,c,d'中的位置是2。
find_in_set函数可以用在where子句中,来筛选出满足某个条件的记录。例如,如果有一个表test1,其中有一个字段list,存储了一些由逗号分隔的值,如'篮球,足球,羽毛球',那么可以用find_in_set函数来查询出包含'足球'的记录。
sql
mysql> select*from votes where find_in_set('动漫',hobby);
mysql> select*from votes where find_in_set('游戏',hobby) and find_in_set('动漫',hobby);