【MySQL】数据类型

> 作者:დ旧言~

> 座右铭:松树千年终是朽,槿花一日自为荣。

> 目标:了解并掌握MYSQL的数据类型,并且能熟练创建表。

> 毒鸡汤:有些事情,总是不明白,所以我不会坚持。早安!

> 专栏选自:带你玩转MySQL

> 望小伙伴们点赞👍收藏✨加关注哟💕💕

​​​

一、前言

想必大家在学校也学习过MySQL,可能学的懵懵懂懂,这个板块我们从入门开始,从最新的安装MySQL到学习MySQL语句,一步一步开始,一切都是新的,新的板块新的开始,大家一起努力,一起进步!!!

主体

学习【MySQL】数据类型咱们按照下面的图解:

2.1数据类型分类

  • 数值类型:用于存储数值,包括整型和浮点型,如 int、double、float等。
  • 字符串类型:用于存储字符串,包括固定长度的char和可变长度的varchar,以及blob和text类型等。
  • 日期和时间类型:用于存储日期和时间,包括date、time、datetime、timestamp等。
  • 枚举类型:用于存储枚举值,例如 enum型。
  • 集合类型:用于存储一组值,例如set类型。
  • 注意:枚举类型和集合类型都属于字符串,因此它们被归为了String类型。

2.2数值类型

2.2.1tinytin类型

语法:

cpp 复制代码
create table t1(num tinyint);

使用:

数值越界测试:

cpp 复制代码
mysql> insert into t1 values (127);
Query OK, 1 row affected (0.00 sec)

mysql> insert into t1 values (128);
1264 - Out of range value for column 'num' at row 1
mysql> insert into t1 values (-128);
Query OK, 1 row affected (0.00 sec)

mysql> insert into t1 values (0);
Query OK, 1 row affected (0.00 sec)

mysql> insert into t1 values (100);
Query OK, 1 row affected (0.00 sec)
  • 这里我们可以看到,如果插入的数据超过数值类型所能表示的范围,MySQL将不允许该数据插入。因为无法得知该数据是截断后的数据还是未经截断的数据。这里体现出了MySQL保证了数据库中数据的可靠性。
  • 同时,超过数据类型范围的数据无法插入到表中也是一种 约束。约束是指在创建表时规定的对表中的数据进行限制的条件。它可以对表中某列或某几列添加一些限制条件,以保证表中的数据符合要求

注意:

  • 在MySQL中,整型可以指定是有符号的和无符号的,默认是有符号的。
  • 可以通过unsigned来说明某个字段是无符号的。

2.2.2bit类型

语法:

位字段类型。M表示每个值的位数,范围从1到64。如果M被忽略,默认为1。

使用:

cpp 复制代码
mysql> create table if not exists t3(
    -> id int,
    -> online bit(1)
    -> );
Query OK, 0 rows affected (0.02 sec)
 
mysql> insert into t3 (id,online) values (1,0);
Query OK, 1 row affected (0.00 sec)
 
mysql> insert into t3 (id,online) values (2,1);
Query OK, 1 row affected (0.01 sec)
 
mysql> insert into t3 (id,online) values (3,2);
ERROR 1406 (22001): Data too long for column 'online' at row 1
mysql> select* from t3;
+------+--------+
| id   | online |
+------+--------+
|    1 |        |
|    2 |       |
+------+--------+

解释:

这里对于插入越界的数据依旧是拦截不让插入,还有这里的0/1不显示,这是因为bit字段在显示时,是按照ASCII码对应的值显示,这里的0/1对应的ASCII码是不显示的。

修改后:

cpp 复制代码
create table t4(name varchar(32), gender bit(1));

2.2.3小数类型

2.2.3.1float

语法:

float[(m, d)] [unsigned] : M指定显示长度,d指定小数位数,占用空间4个字节。

**举个栗子:**float(4,2)表示的范围是-99.99 ~ 99.99,MySQL在保存值时会进行四舍五入

cpp 复制代码
mysql> create table if not exists t4(
    -> id int,
    -> salary float(4,2)
    -> );
Query OK, 0 rows affected (0.02 sec)
 
mysql> insert into t4 (id,salary) values (1,-99.99);
Query OK, 1 row affected (0.00 sec)
 
mysql> insert into t4 (id,salary) values (2,99.99);
Query OK, 1 row affected (0.01 sec)
 
mysql> insert into t4 (id,salary) values (2,23.145);
Query OK, 1 row affected (0.00 sec)
 
mysql> insert into t4 (id,salary) values (2,-99.994);
Query OK, 1 row affected (0.01 sec)
 
mysql> insert into t4 (id,salary) values (2,-99.995);
ERROR 1264 (22003): Out of range value for column 'salary' at row 1
mysql> insert into t4 (id,salary) values (2,99.994);
Query OK, 1 row affected (0.00 sec)
 
mysql> insert into t4 (id,salary) values (2,99.995);
ERROR 1264 (22003): Out of range value for column 'salary' at row 1
mysql> select* from t4;
+------+--------+
| id   | salary |
+------+--------+
|    1 | -99.99 |
|    2 |  99.99 |
|    2 |  23.14 |
|    2 | -99.99 |
|    2 |  99.99 |
+------+--------+

说明:

  • 会发现对于超过指定位数的,会四舍五入进行保存,保存后的数据只要在范围内就可以正常插入,不在范围的就会直接拦截,况且float对于数据有时是不能准确保存的 。
  • 如果定义的是float(4,2) unsigned 这时,因为把它指定为无符号的数,范围是 0 ~ 99.99

2.2.4decimal

语法:

decimal(m, d) [unsigned] : 定点数m指定长度,d表示小数点的位数

decimal(5,2) 表示的范围是 -999.99 ~ 999.99

使用:

cpp 复制代码
mysql> create table if not exists t5(
    -> id int,
    -> s1 float(10,8),
    -> s2 decimal(10,8)
    -> );
Query OK, 0 rows affected (0.02 sec)
 
mysql> insert into t5 (id,s1,s2) values (1,23.12345612,23.12345612);
Query OK, 1 row affected (0.00 sec)
 
mysql> select* from t5;
+------+-------------+-------------+
| id   | s1          | s2          |
+------+-------------+-------------+
|    1 | 23.12345695 | 23.12345612 |
+------+-------------+-------------+

说明:

  • float表示的精度大约是7位。
  • decimal整数最大位数m为65。支持小数最大位数d是30。如果d被省略,默认为0.如果m被省略,默认是10。
  • 建议:如果希望小数的精度高,推荐使用decimal。

2.3字符串类型


2.3.1char

语法:

固定长度字符串,L是可以存储的长度,单位为字符,最大长度值可以为255。

在utf8编码当中,一个汉字为一个字符,一个字符为三字节

举个栗子:

sql 复制代码
mysql> create table t6(
    -> id int,
    -> name char(3)
    -> );
Query OK, 0 rows affected (0.02 sec)
 
mysql> insert into t6 (id,name) values (1,'中');
Query OK, 1 row affected (0.00 sec)
 
mysql> insert into t6 (id,name) values (1,'中国');
Query OK, 1 row affected (0.00 sec)
 
mysql> insert into t6 (id,name) values (1,'中国人');
Query OK, 1 row affected (0.00 sec)
 
mysql> insert into t6 (id,name) values (1,'中国人民');
ERROR 1406 (22001): Data too long for column 'name' at row 1

2.3.2varchar

语法:

可变长度字符串,L表示字符长度,最大长度65535个字节

举个栗子:

sql 复制代码
mysql> create table tt11(name varchar(21845))charset=utf8; --验证了utf8确实是不能超过21844
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type,
not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs
 
mysql> create table tt11(name varchar(21844)) charset=utf8;
Query OK, 0 rows affected (0.01 sec)

解释:

  • 变长字符串是指长度可变的字符串,即字符串长度不固定,可以根据实际需要存储不同长度的字符数据。varchar 类型的字段会根据存储的实际数据长度来占用相应的存储空间,因此它比 char 类型更加灵活,能够在存储短字符串时占用更少的存储空间。
  • 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 字节)。

2.3.3char和varchar比较

图解:

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

  • 如果数据确定长度都一样,就使用定长(char),比如:身份证,手机号,md5
  • 如果数据长度有变化,就使用变长(varchar), 比如:名字,地址,但是你要保证最长的能存的进去。
  • 定长的磁盘空间比较浪费,但是效率高。
  • 变长的磁盘空间比较节省,但是效率低。
  • 定长的意义是,直接开辟好对应的空间
  • 变长的意义是,在不超过自定义范围的情况下,用多少,开辟多少

2.3.4日期和时间类型

分类:

  • date:用于存储日期(年、月、日)。其格式为 'YYYY-MM-DD',其中 YYYY 表示四位年份,MM 表示月份(01-12),DD 表示日期(01-31)。date 数据类型占用 3 个字节。
  • datetime:用于存储日期和时间(年、月、日、时、分、秒)。其格式为 'YYYY-MM-DD HH:MM:SS',其中 YYYY 表示四位年份,MM 表示月份(01-12),DD 表示日期(01-31),HH 表示小时(00-23),MM 表示分钟(00-59),SS 表示秒(00-59)。datetime 数据类型占用 8 个字节。
  • timestamp:用于存储日期和时间(年、月、日、时、分、秒),且其值自动随系统时间的更改而更新。其格式与 datetime 相同,但是其取值范围比 datetime 更小。timestamp 数据类型占用 4 个字节。
  • 时间戳(timestamp) 是一种特殊的数据类型,用于表示某个时间点。在 MySQL 中,时间戳通常指 Unix 时间戳,它表示自 1970 年 1 月 1 日 0 时 0 分 0 秒(UTC 时区)起到某个时间点的秒数。
  • 在 MySQL 中,timestamp 类型可以自动更新为当前时间,比如在插入新记录时,可以将 timestamp 列设置为默认值 CURRENT_TIMESTAMP,这样每当插入一条新记录时,该列的值都会自动更新为当前时间。

举个栗子:

sql 复制代码
mysql> create table t7(
    -> t1 date,
    -> t2 datetime,
    -> t3 timestamp
    -> );
Query OK, 0 rows affected (0.03 sec)
 
mysql> insert into t7 (t1,t2) values ('2003-08-15','2008-08-10 12:01:01');
Query OK, 1 row affected (0.01 sec)
 
mysql> select* from t7;
+------------+---------------------+---------------------+
| t1         | t2                  | t3                  |
+------------+---------------------+---------------------+
| 2003-08-15 | 2008-08-10 12:01:01 | 2024-09-13 09:33:34 |
+------------+---------------------+---------------------+
1 row in set (0.01 sec)
 
mysql> update t7 set t1='1999-12-31'; #更新数据;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0
 
mysql> select* from t7;
+------------+---------------------+---------------------+
| t1         | t2                  | t3                  |
+------------+---------------------+---------------------+
| 1999-12-31 | 2008-08-10 12:01:01 | 2024-09-13 09:34:30 |
+------------+---------------------+---------------------+
1 row in set (0.00 sec)
 
mysql> create table if not exists t8(
    -> context text,
    -> time timestamp
    -> );
Query OK, 0 rows affected (0.03 sec)
 
mysql> insert into t8 (context) values ('中国人民');
Query OK, 1 row affected (0.00 sec)
 
mysql> select* from t8;
+--------------+---------------------+
| context      | time                |
+--------------+---------------------+
| 中国人民     | 2024-09-13 09:36:39 |
+--------------+---------------------+
1 row in set (0.00 sec)
 
mysql> update t8 set context='中国人民站起来了'; #更新数据
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0
 
mysql> select* from t8;
+--------------------------+---------------------+
| context                  | time                |
+--------------------------+---------------------+
| 中国人民站起来了         | 2024-09-13 09:37:27 |
+--------------------------+---------------------+
1 row in set (0.00 sec)

2.3.5enum和set

解释:

  • enum 是一种多选一的数据类型,它可以存储一个固定的选项列表中的一个值,支持最多 65535 个元素,每个元素的长度不超过 65535 个字节。在创建表时,可以使用 enum(column_name,'option1','option2',...) 指定列名和选项列表,其中列名是必须的,选项列表中至少要有一个选项。出于效率考虑,这些值实际存储的是数字。因为这些选项的每个选项值依次对应如下数字:1,2,3,... 最多 65535 个;当我们添加枚举值时,也可以添加对应的数字编号。
  • set 是一种多选多的数据类型,它可以存储一个固定的选项列表中的多个值,支持最多 64 个元素,每个元素的长度不超过 64 个字节。在创建表时,可以使用 set(column_name,'option1','option2',...) 指定列名和选项列表,其中列名是必须的,选项列表中至少要有一个选项。出于效率考虑,这些值实际存储的是数字,因为这些选项的每个选项值依次对应如下数字:1,2,4,8,16,32,... 最多 64 个。
  • 不建议在添加枚举值,集合值的时候采用数字的方式,因为不利于阅读。\n示例:\n有一个调查表 votes,需要调查人的喜好, 比如在集合(唱,跳,rap,打篮球)中去选择(可以多选),同时填表人还需要填写自己的性别男或女(单选)。

举个栗子:

sql 复制代码
mysql> create table if not exists t9(
    -> name varchar(20),
    -> gender enum('男','女'),
    -> hobby set('代码','羽毛球','乒乓球','足球')
    -> );
Query OK, 0 rows affected (0.03 sec)
 
mysql> insert into t9 (name,gender,hobby) values ('刘备','男','代码');
Query OK, 1 row affected (0.00 sec)
 
mysql> insert into t9 (name,gender,hobby) values ('孙尚香','女','代码,羽毛球');
Query OK, 1 row affected (0.00 sec)
 
#插入enum和set中不存在的值就会报错
mysql> insert into t9 (name,gender,hobby) values ('刘禅','unknown','代码,羽毛球');
ERROR 1265 (01000): Data truncated for column 'gender' at row 1
mysql> insert into t9 (name,gender,hobby) values ('刘禅','unknown','跑步');
ERROR 1265 (01000): Data truncated for column 'gender' at row 1
 
 
#enum在插入时可以写枚举常量值,也可以写常量对应下标(从1开始)
mysql> insert into t9 (name,gender,hobby) values ('曹操',1,'代码');
Query OK, 1 row affected (0.01 sec)
 
mysql> insert into t9 (name,gender,hobby) values ('貂蝉',2,'代码');
Query OK, 1 row affected (0.00 sec)
 
mysql> select* from t9;
+-----------+--------+------------------+
| name      | gender | hobby            |
+-----------+--------+------------------+
| 刘备      | 男     | 代码             |
| 孙尚香    | 女     | 代码,羽毛球      |
| 曹操      | 男     | 代码             |
| 貂蝉      | 女     | 代码             |
+-----------+--------+------------------+
 
 
#set值在用数字时,是按照数字二进制bit位是否为1进行的
mysql> insert into t9 (name,gender,hobby) values ('孙权',1,1);
Query OK, 1 row affected (0.00 sec)
 
mysql> insert into t9 (name,gender,hobby) values ('周瑜',1,2);
Query OK, 1 row affected (0.00 sec)
 
mysql> insert into t9 (name,gender,hobby) values ('赵云',1,3);
Query OK, 1 row affected (0.00 sec)
 
mysql> insert into t9 (name,gender,hobby) values ('张飞',1,4);
Query OK, 1 row affected (0.01 sec)
 
mysql> insert into t9 (name,gender,hobby) values ('关羽',1,5);
Query OK, 1 row affected (0.00 sec)
 
mysql> insert into t9 (name,gender,hobby) values ('黄忠',1,6);
Query OK, 1 row affected (0.00 sec)
 
mysql> insert into t9 (name,gender,hobby) values ('马超',1,15);
Query OK, 1 row affected (0.01 sec)
 
mysql> select* from t9;
+-----------+--------+-----------------------------------+
| name      | gender | hobby                             |
+-----------+--------+-----------------------------------+
| 刘备      | 男     | 代码                              |
| 孙尚香    | 女     | 代码,羽毛球                       |
| 曹操      | 男     | 代码                              |
| 貂蝉      | 女     | 代码                              |
| 孙权      | 男     | 代码                              |
| 周瑜      | 男     | 羽毛球                            |
| 赵云      | 男     | 代码,羽毛球                       |
| 张飞      | 男     | 乒乓球                            |
| 关羽      | 男     | 代码,乒乓球                       |
| 黄忠      | 男     | 羽毛球,乒乓球                     |
| 马超      | 男     | 代码,羽毛球,乒乓球,足球           |
+-----------+--------+-----------------------------------+
 

查找:

  • 使用select* from 表名 where 列名=常量/数字这样查的话,是严格匹配去查找的,有多兴趣的是查不出来的,此时就可以使用find_in_set函数来查询
  • find_in_set(sub,str_list) :如果 sub 在 str_list 中,则返回下标;如果不在,返回0; str_list 用逗号分隔的字符串。

查询爱好中包含乒乓球的人:

sql 复制代码
mysql> select* from t9 where find_in_set('乒乓球',hobby);
 
+--------+--------+-----------------------------------+
| name   | gender | hobby                             |
+--------+--------+-----------------------------------+
| 张飞   | 男     | 乒乓球                            |
| 关羽   | 男     | 代码,乒乓球                       |
| 黄忠   | 男     | 羽毛球,乒乓球                     |
| 马超   | 男     | 代码,羽毛球,乒乓球,足球           |
+--------+--------+-----------------------------------+

三、结束语

今天内容就到这里啦,时间过得很快,大家沉下心来好好学习,会有一定的收获的,大家多多坚持,嘻嘻,成功路上注定孤独,因为坚持的人不多。那请大家举起自己的小手给博主一键三连,有你们的支持是我最大的动力💞💞💞,回见。

​​​​

相关推荐
aqi0018 分钟前
FFmpeg开发笔记(七十二)Linux给FFmpeg集成MPEG-5视频编解码器EVC
android·ffmpeg·音视频·流媒体
Ein hübscher Kerl.19 分钟前
虚拟机上安装 MariaDB 及依赖包
数据库·mariadb
长征coder33 分钟前
AWS MySQL 读写分离配置指南
mysql·云计算·aws
醇醛酸醚酮酯1 小时前
Qt项目锻炼——TODO清单(二)
开发语言·数据库·qt
ladymorgana1 小时前
【docker】修改 MySQL 密码后 Navicat 仍能用原密码连接
mysql·adb·docker
PanZonghui1 小时前
Centos项目部署之安装数据库MySQL8
linux·后端·mysql
GreatSQL社区1 小时前
用systemd管理GreatSQL服务详解
数据库·mysql·greatsql
掘根1 小时前
【MySQL进阶】错误日志,二进制日志,mysql系统库
数据库·mysql
weixin_438335402 小时前
基础知识:mysql-connector-j依赖
数据库·mysql
小明铭同学2 小时前
MySQL 八股文【持续更新ing】
数据库·mysql