【MySQL】数据类型

文章目录

  • 1. 整型
  • 2. 位字段
  • 3. 浮点数
    • float
    • decimal
  • 4.文本类型
    • char
    • varchar
    • char VS varchar
  • 5. 日期和时间类型
  • 6. enum和set


1. 整型

类型 字节数 带符号范围 无符号范围
tinyint 1 [-128, 127] [0, 255]
smallint 2 [-32768, 32767] [0, 65535]
mediumint 3 [-8388608, 8388607] [0, 16777215]
int 4 [-2147483648, 214748367] [0, 4294967295]
bigint 8 [-9223372036854775808, 9223372036854775807] [18446744073709551615]
  • 注入数据库的数字不在类型的范围内,MySQL拦截

  • 整型默认是有符号的,在类型后面加上关键字unsigned,说明某个字段是无符号的

2. 位字段

bit位字段类型,可以指定有多少个比特位,最大是64位,最小是1位。

create table t1( flag bit(8)) #example

bit后括号中的数字表示一共有多少个比特位,不显式指明默认为1

create table t1( flag bit) #该表有一列, 数据类型为1个比特位
  • bit位字段也是有范围的,这取决于bit的位数,如bit(8)的范围是[0, 255] (全0到全1),而bit(1)只能表示0或1。

  • bit位字段以ASCII对应的值显示,所以对于一些较小的值,可能对应无法显示的ascii码,也就显示不出来了。

【MySQL】数据类型_第1张图片

3. 浮点数

float

float[(m, d)][unsigned] #[]为可选项
  • m表示显示长度(整数和小数的总位数),d表示小数精确位数,unsigned可以指定为无符号

  • float占4个字节

  • float的m和d可以不显式地指定

  • m的最大值为255,d的最大值为30

示例:

create table t3(score, float(4, 2));

float(4, 2)表示的范围是:[-99.99, 99.99]

mysql> create table t3( name varchar(20), score float(4, 2) );
Query OK, 0 rows affected (0.03 sec)

mysql> desc t3;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| name  | varchar(20) | YES  |     | NULL    |       |
| score | float(4,2)  | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

mysql> insert into t3 values ('张三', 99.99);
Query OK, 1 row affected (0.00 sec)

mysql> insert into t3 values ('李四', -99.99);
Query OK, 1 row affected (0.00 sec)

mysql> insert into t3 values ('王五', 59.87349);
Query OK, 1 row affected (0.00 sec)

mysql> insert into t3 values ('赵六', 99.996);
ERROR 1264 (22003): Out of range value for column 'score' at row 1
mysql> insert into t3 values ('赵六', 99.994);
Query OK, 1 row affected (0.00 sec)

mysql> select * from t3;
+--------+--------+
| name   | score  |
+--------+--------+
| 张三   |  99.99 |
| 李四   | -99.99 |
| 王五   |  59.87 |
| 赵六   |  99.99 |
+--------+--------+
4 rows in set (0.00 sec)

MySQL在保存浮点数时会四舍五入,如demo中59.87349存入float(4, 2)类型的列中,因为精确到小数点后2位,所以会保存为59.87。四舍五入有时也会影响越界问题,如demo中的99.996,四舍五入后是100.00,超过数据范围,无法插入;而99.994四舍五入后是99.99,可以插入。

float(4, 2) unsigned表示的范围是:[00.00(0), 99.99]

  • double类型的语法与float基本相同,占8个字节。

decimal

decimal是精度更高的浮点数

decimal(m, d)[unsigned]
  • m表示显示长度(整数和小数的总位数),d表示小数精确位数,unsigned可以指定为无符号
  • decimal的m和d必须显式地指定,其字节大小为随m和d的大小而改变
  • m的最大值为65,d的最大值为30
mysql> create table t4(
    -> f float(16,8),
    -> d decimal(16,8)
    -> );
Query OK, 0 rows affected (0.03 sec)

mysql> desc t4;
+-------+---------------+------+-----+---------+-------+
| Field | Type          | Null | Key | Default | Extra |
+-------+---------------+------+-----+---------+-------+
| f     | float(16,8)   | YES  |     | NULL    |       |
| d     | decimal(16,8) | YES  |     | NULL    |       |
+-------+---------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

mysql> insert into t4 (f, d) values (12345678.12345678, 12345678.12345678);
Query OK, 1 row affected (0.01 sec)

mysql> select * from t4;
+-------------------+-------------------+
| f                 | d                 |
+-------------------+-------------------+
| 12345678.00000000 | 12345678.12345678 |
+-------------------+-------------------+
1 row in set (0.00 sec)

可以看到,相同长度和小数位数的float和decimal,插入相同比较大的小数,decimal的精度比float更高。因此,若想要存储高精度的数据,选择decimal更合适。


4.文本类型

char

char(L)
  • char是固定长度字符串,由L指定字符串长度,单位为字符,最大长度值是255
  • 在MySQL中,字符可以是一个字母、一个数字、甚至是一个汉字。这里要和C/C++的char类型区分开
  • char(0)只能存储空字符串''
mysql> create table t5(
    -> subject char(2)
    -> ); # subject最多存储两个字符
Query OK, 0 rows affected (0.03 sec)

mysql> insert into t5 values('eg');
Query OK, 1 row affected (0.01 sec)

mysql> insert into t5 values('pe');
Query OK, 1 row affected (0.00 sec)

mysql> insert into t5 values('pdd'); #3个字符,插入失败
ERROR 1406 (22001): Data too long for column 'subject' at row 1
mysql> insert into t5 values('数学'); #两个汉字也被视为两个字符,可以插入
Query OK, 1 row affected (0.00 sec)

mysql> insert into t5 values('语文');
Query OK, 1 row affected (0.00 sec)

mysql> insert into t5 values('英语');
Query OK, 1 row affected (0.00 sec)

mysql> insert into t5 values('生物学'); #3个汉字同样插入失败
ERROR 1406 (22001): Data too long for column 'subject' at row 1 

mysql> select * from t5;
+---------+
| subject |
+---------+
| eg      |
| pe      |
| 数学     |
| 语文     |
| 英语     |
+---------+
5 rows in set (0.00 sec)

varchar

varchar(L)
  • 可变长字符串,和char(L)相同,这里的L也是字符的长度,最大字节长度是65535
  • varchar指定的长度是变长字符串的最大长度,例如:varchar(10)可以表示包含0~10个字符的字符串(0个字符是空串),需要多少空间就开辟多少。

关于varchar(L)中L的范围

  1. varchar长度可以指定0~65535,但是有1-3个字节数(根据varchar长度变化)是用于记录字符串长度的,因此有效长度的最大值是65532

  2. 当我们的表的编码是utf8时,varchar(L)的参数L最大值是65532/3=21844(因为utf中,一个字符占用3个字节);如果编码是gbk,varchar(L)的参数L最大是65532/2=32766(因为gbk中,一个字符占用2字节)

mysql> create table t6 (
    -> content varchar(21844)
    -> ) charset=utf8; #编码是utf8
Query OK, 0 rows affected (0.03 sec)

mysql> create table t7 ( content varchar(21845) ) 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

mysql> create table t7 (
    -> content varchar(32766)
    -> ) charset=gbk; #编码是gbk
Query OK, 0 rows affected (0.03 sec)

mysql> create table t8 ( content varchar(32767) ) charset=gbk; #越界创建失败
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

char VS varchar

char和varchar的区别

  • char是固定长度字符串,规定长度为多少,创建时就开辟多大的空间,类比C/C++中的数字char[N]

  • varchar是变长字符串,规定的是最大字符串长度,创建时只开辟需要的空间大小,只要不超过最大长度,类比C++中的std::string

同在utf8编码下具体存储区别:

存储字符串 char(8)占用字节数 varchar(8)占用字节数
ABCD 8*3 = 24 4*3 + 1 = 13
ABCDEFG 8*3 = 24 8*3 + 1 = 25
ABCDEFGH 数据超过长度 数据超过长度
  1. 在数据长度比较固定时(如:身份证号、手机号),使用定长字符串类型char
  2. 在数据长度变化较大时(如:人名,地名),使用变长字符串类型varchar
  3. 定长类型比较消耗磁盘空间,但是存储效率高;变长类型比较节省磁盘空间,但是存储效率低,因为还要计算实际存储长度
  4. 定长的意义是,直接开辟好对应的空间;变长的意义是,在不超过自定义范围的情况下,用多少,开辟多少。

5. 日期和时间类型

  • date: 日期类型,格式为:‘年-月-日’,占用3个字节
  • datetime: 日期时间类型,格式为:‘年-月-日 时:分:秒’,占用8个字节
  • timestamp: 时间戳,格式与datetime相同,占用4个字节。timestamp所在行发生变化时,MySQL会自动将其修改为当前时间
mysql> create table t8( name varchar(20), birthday date, birthtime datetime, curtime timestamp );
Query OK, 0 rows affected (0.02 sec)

mysql> insert into t8 (name, birthday, birthtime) values ('张三', '2003-4-25', '2003-4-25 8:24:01');
Query OK, 1 row affected (0.00 sec)

mysql> insert into t8 (name, birthday, birthtime) values ('李四', '2000-10-1', '2000-10-1 8:00:00');
Query OK, 1 row affected (0.01 sec)

mysql> select * from t8; #观察到MySQL自动填入curtime字段
+--------+------------+---------------------+---------------------+
| name   | birthday   | birthtime           | curtime             |
+--------+------------+---------------------+---------------------+
| 张三   | 2003-04-25 | 2003-04-25 08:24:01 | 2023-12-09 18:07:05 |
| 李四   | 2000-10-01 | 2000-10-01 08:00:00 | 2023-12-09 18:07:32 |
+--------+------------+---------------------+---------------------+
2 rows in set (0.00 sec)

mysql> update t8 set name='王五' where name='李四';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from t8; #修改数据,时间戳会自动更新
+--------+------------+---------------------+---------------------+
| name   | birthday   | birthtime           | curtime             |
+--------+------------+---------------------+---------------------+
| 张三   | 2003-04-25 | 2003-04-25 08:24:01 | 2023-12-09 18:07:05 |
| 王五   | 2000-10-01 | 2000-10-01 08:00:00 | 2023-12-09 18:08:54 |
+--------+------------+---------------------+---------------------+
2 rows in set (0.00 sec)


6. enum和set

enum: 枚举,单选类型。提供一些选项,最终定义为该类型的单元格,可从选项中选择一个作为单元值。每个选项实际存储的都是数字编号,依次是1,2,3,4…,最大是65535。

set: 集合,多选类型。提供一些选项,最终定义为该类型的单元格,可从选项中选择多个作为单元值。每个选项也有对应的数字编号,依次是1,2,4,8,16…,最多有64个选项(每个选项都是只有一个比特位为1)。

如:

set('音乐','电竞','运动'), 1(001)对应’音乐’,2(010)对应’电竞’,4(100)对应’运动’,以此类推。

mysql> create table t9(
    -> name varchar(20),
    -> gender enum('男','女','未知'),
    -> music set('说唱', '流行', '古典', '爵士', '其它')
    -> );
Query OK, 0 rows affected (0.03 sec)

mysql> desc t9;
+--------+---------------------------------------------------+------+-----+---------+-------+
| Field  | Type                                              | Null | Key | Default | Extra |
+--------+---------------------------------------------------+------+-----+---------+-------+
| name   | varchar(20)                                       | YES  |     | NULL    |       |
| gender | enum('男','女','未知')                            | YES  |     | NULL    |       |
| music  | set('说唱','流行','古典','爵士','其它')           | YES  |     | NULL    |       |
+--------+---------------------------------------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

mysql> insert into t9 (name, gender, music) values ('Jcole', '男', '说唱'); #enum和set都以选项字符串值插入
Query OK, 1 row affected (0.00 sec)

mysql> insert into t9 (name, gender, music) values ('Adele', 2, '流行'); #enum以选项数字编号插入
Query OK, 1 row affected (0.01 sec)

mysql> insert into t9 (name, gender, music) values ('Jchou', 1, '说唱,流行'); #set插入多个是'XX, YY, ZZ...'
Query OK, 1 row affected (0.00 sec)

mysql> insert into t9 (name, gender, music) values ('Capper', 1, 1); #set也能以数字编号插入
Query OK, 1 row affected (0.01 sec)

mysql> insert into t9 (name, gender, music) values ('Tim', 1, 8); #8->1000->对应第四个选项'爵士'
Query OK, 1 row affected (0.00 sec)

mysql> insert into t9 (name, gender, music) values ('John', 1, 12); #12->1100->对应第三和第四个选项
Query OK, 1 row affected (0.01 sec)

mysql> select * from t9;
+--------+--------+---------------+
| name   | gender | music         |
+--------+--------+---------------+
| Jcole  || 说唱          |
| Adele  || 流行          |
| Jchou  || 说唱,流行     |
| Capper || 说唱          |
| Tim    || 爵士          |
| John   || 古典,爵士     |
+--------+--------+---------------+
6 rows in set (0.00 sec)

enum和set的查找

mysql> select * from t9;
+--------+--------+---------------+
| name   | gender | music         |
+--------+--------+---------------+
| Jcole  || 说唱           |
| Adele  || 流行           | 
| Jchou  || 说唱,流行       |
| Capper || 说唱           |
| Tim    || 爵士           |
| John   || 古典,爵士       |
+--------+--------+---------------+
6 rows in set (0.00 sec)

mysql> select * from t9 where gender = '男';
+--------+--------+---------------+
| name   | gender | music         |
+--------+--------+---------------+
| Jcole  || 说唱          |
| Jchou  || 说唱,流行     |
| Capper || 说唱          |
| Tim    || 爵士          |
| John   || 古典,爵士     |
+--------+--------+---------------+
5 rows in set (0.00 sec)

mysql> select * from t9 where gender = 0;
Empty set (0.00 sec)

mysql> select * from t9 where gender = 2;
+-------+--------+--------+
| name  | gender | music  |
+-------+--------+--------+
| Adele || 流行   |
+-------+--------+--------+
1 row in set (0.00 sec)

mysql> select * from t9 where music = '说唱';
+--------+--------+--------+
| name   | gender | music  |
+--------+--------+--------+
| Jcole  || 说唱   |
| Capper || 说唱   |
+--------+--------+--------+
2 rows in set (0.00 sec)

mysql> select * from t9 where music = 3;
+-------+--------+---------------+
| name  | gender | music         |
+-------+--------+---------------+
| Jchou || 说唱,流行     |
+-------+--------+---------------+
1 row in set (0.00 sec)

mysql> select * from t9 where find_in_set('说唱', music); #find_in_set能找到包含sub的
+--------+--------+---------------+
| name   | gender | music         |
+--------+--------+---------------+
| Jcole  || 说唱          |
| Jchou  || 说唱,流行     |
| Capper || 说唱          |
+--------+--------+---------------+
3 rows in set (0.00 sec)

mysql> select * from t9 where find_in_set('说唱', music) and find_in_set('流行', music);
+-------+--------+---------------+
| name  | gender | music         |
+-------+--------+---------------+
| Jchou || 说唱,流行     |
+-------+--------+---------------+
1 row in set (0.00 sec)

你可能感兴趣的:(MYSQL,mysql)