mysql> create table dk(
-> num tinyint);
Query OK, 0 rows affected (0.01 sec)
mysql> insert into dk values(-128);
Query OK, 1 row affected (0.01 sec)
mysql> insert into dk values(-129);
ERROR 1264 (22003): Out of range value for column 'num' at row 1
当插入范围之外的值时,mysql会报错,而后面我们也会学习到数据类型实际上就是一种约束,保证了数据的可靠性。
此外数值类型可以使用unsigned说明某个字段是无符号的。
mysql> create table dk2( num tinyint unsigned);
Query OK, 0 rows affected (0.01 sec)
mysql> insert into dk2 values(-129);
ERROR 1264 (22003): Out of range value for column 'num' at row 1
mysql> insert into dk2 values(-1);
ERROR 1264 (22003): Out of range value for column 'num' at row 1
mysql> insert into dk2 values(0);
Query OK, 1 row affected (0.00 sec)
可以看见只能插入大于等于0的数字。
bit [(M)] : 位字段类型。 M 表示每个值二进制的位数,范围从 1 到 64 。如果 M 被忽略,默认为 1 。
根据位图所学,比特位指定了位数,那么其表示的最大值是2^M-1。如:
mysql> create table bite(
-> id int,
-> ^C
mysql> create table bite(
-> id int(4),
-> num bit(4));
Query OK, 0 rows affected (0.02 sec)
mysql> insert into bite values(10,20);
ERROR 1406 (22001): Data too long for column 'num' at row 1
mysql> insert into bite values(10,15);
Query OK, 1 row affected (0.00 sec)
4位的位图,最大只能表示15,所以插入20是会报错的。
mysql> select* from bite;
+------+------+
| id | num |
+------+------+
| 10 | |
+------+------+
可以看到插入的15并没有显示出来。这是因为bit字段在显示时,是按照ASCII码对应的值显示。
mysql> select hex(num) from bite;
+----------+
| hex(num) |
+----------+
| F |
+----------+
1 row in set (0.00 sec)
我们把对应的插入数据采用16进制方式打印出来。
mysql> create table bite(
-> id int(8),
-> num bit(8));
Query OK, 0 rows affected (0.02 sec)
mysql> insert into bite values(10000000,97);
Query OK, 1 row affected (0.00 sec)
mysql> insert into bite values(10000001,'a');
Query OK, 1 row affected (0.00 sec)
mysql> select * from bite;
+----------+------+
| id | num |
+----------+------+
| 10000000 | a |
| 10000001 | a |
+----------+------+
2 rows in set (0.00 sec)
因为a的ASCII码是97所以也能直接插入该字母,可以看到97对应的是字母a。
此外int数值类型后面跟的位数表示的是这个数10进制的位数,而bit位图是二进制的位数。
如果位图只需要插入0或者1,那我们可以直接开一个bit(1)即可。
float[(m, d)] [unsigned] : M指定显示长度,d指定小数位数,占用空间4个字节
mysql> create table t(num float(4,2));
Query OK, 0 rows affected (0.02 sec)
mysql> insert into t values(10.00);
Query OK, 1 row affected (0.01 sec)
mysql> insert into t values(99.93);
Query OK, 1 row affected (0.00 sec)
mysql> insert into t values(99.99);
Query OK, 1 row affected (0.00 sec)
mysql> insert into t values(100.00);
ERROR 1264 (22003): Out of range value for column 'num' at row 1
mysql> insert into t values(-99.99);
Query OK, 1 row affected (0.00 sec)
mysql> insert into t values(-100.0);
ERROR 1264 (22003): Out of range value for column 'num' at row 1
mysql> insert into t values(-100.0);
4位有效长度,2位小数,那么表示的范围就是-99.99----99.99。同样的float也可以采用unsigned。
mysql> select * from t;
+--------+
| num |
+--------+
| 10.00 |
| 99.93 |
| 99.99 |
| -99.99 |
+--------+
4 rows in set (0.00 sec)
mysql> insert into t values(-99.985);
Query OK, 1 row affected (0.01 sec)
mysql> select * from t;
+--------+
| num |
+--------+
| 10.00 |
| 99.93 |
| 99.99 |
| -99.99 |
| -99.98 |
+--------+
当我们插入范围内的一个有三位小数的数字时,mysql会进行四舍五入。
decimal(m, d) [unsigned] : 定点数m指定长度,d表示小数点的位数
decimal和float很像,但是有区别:
decimal的精度更高。
同时对两表插入23.12345678
得到的结果如下:
mysql> select * from t2;
+-------------+
| num |
+-------------+
| 23.12345695 |
+-------------+
1 row in set (0.00 sec)mysql> select * from t3;
+-------------+
| num |
+-------------+
| 23.12345678 |
+-------------+
说明float的精度大致是在7位(根据不同的mysql版本和系统有所不同可能)
char(L): 固定长度字符串,L是可以存储的长度,单位为字符,最大长度值可以为255
注意:单位是字符
mysql> create table t(
-> name char(2));
Query OK, 0 rows affected (0.02 sec)
mysql> insert into t values('中国');
Query OK, 1 row affected (0.00 sec)
如果在c++中中国会被识别成4个字符,但是mysql中的char单位就是字符,中国就是2个字符。
varchar(L): 可变长度字符串, L 表示字符长度,最大长度 65535 个字节
注意:L表示的是字符长度。
mysql> create table t2(
-> name varchar(6));
Query OK, 0 rows affected (0.02 sec)
mysql> insert into t2 values('我爱你,中国');
Query OK, 1 row affected (0.00 sec)
mysql> select * from t2;
+------------------+
| name |
+------------------+
| 我爱你,中国 |
+------------------+
mysql> create table t2( name varchar(65535));
ERROR 1074 (42000): Column length too big for column 'name' (max = 21845); use BLOB or TEXT instead
当我想创建65535字节大小的时候会报错,为什么呢,因为len代表的是字符,而len这里是有要求的。
关于 varchar(len),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 字节)。
date :日期 'yyyy-mm-dd' ,占用三字节
datetime 时间日期格式 'yyyy-mm-dd HH:ii:ss' 表示范围从 1000 到 9999 ,占用八字节
timestamp :时间戳,从1970年开始的 yyyy-mm-dd HH:ii:ss 格式和 datetime 完全一致,占用四字节
mysql> create table t(
-> t1 date,
-> t2 datetime,
-> t3 timestamp);
insert into t values('2023-11-4','2023-11-4 20:37:33');
ERROR 1136 (21S01): Column count doesn't match value count at row 1
mysql> show create table t;
+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| t | CREATE TABLE `t` (
`t1` date DEFAULT NULL,
`t2` datetime DEFAULT NULL,
`t3` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
第三个字段timestamp通过我们查看表创建的时候,可以看到当我们插入t3字段所在行的数据的时候,t3这里会自动填充上当前系统的时间。也就是说第三行不需要我们插入,所以我们插入的时候如果省略t3 直接后面使用values会报错,因此,需要指定t1和t2字段插入。效果如下:
mysql> insert into t(t1,t2) values('2023-11-4','2023-11-4 20:37:33');
Query OK, 1 row affected (0.00 sec)
mysql> select * from t;
+------------+---------------------+---------------------+
| t1 | t2 | t3 |
+------------+---------------------+---------------------+
| 2023-11-04 | 2023-11-04 20:37:33 | 2023-11-04 20:39:47 |
+------------+---------------------+---------------------+
注意:我们插入的时候月份和日期前面就算不加0,mysql也会自动给我们添加上。
enum:枚举,“多选一”的单选类型
enum('选项一','选项二')
mysql> desc t;
+--------+-------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------------+------+-----+---------+-------+
| name | varchar(4) | YES | | NULL | |
| gender | enum('男','女') | YES | | NULL | |
+--------+-------------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
mysql> insert into t values('张三','男');
Query OK, 1 row affected (0.00 sec)
mysql> insert into t values('张四','女');
Query OK, 1 row affected (0.00 sec)
mysql> insert into t values('张五','人');
ERROR 1265 (01000): Data truncated for column 'gender' at row 1
插入的时候,只要插入enum选项中有的就行,如果是插入的不在enum中,则报错,此外enum也可以通过数字插入:
mysql> insert into t values('张五',1);
Query OK, 1 row affected (0.00 sec)
mysql> insert into t values('张五',2);
Query OK, 1 row affected (0.00 sec)
mysql> select * from t;
+--------+--------+
| name | gender |
+--------+--------+
| 张三 | 男 |
| 张四 | 女 |
| 张五 | 男 |
| 张五 | 女 |
+--------+--------+
4 rows in set (0.00 sec)
mysql> insert into t values('张五',0);
ERROR 1265 (01000): Data truncated for column 'gender' at row 1
可以看到enum中通过数字下标插入默认是从1开始的。
set:集合,“单选多选”都可以。
set('选项一','选项二')
mysql> desc t;
+-------+---------------------------------------------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------------------------------------------------------+------+-----+---------+-------+
| name | varchar(4) | YES | | NULL | |
| hobby | set('写代码','玩游戏','吃饭','睡觉','内卷') | YES | | NULL | |
+-------+---------------------------------------------------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
mysql> insert into t values('张三','玩游戏');
Query OK, 1 row affected (0.00 sec)
mysql> insert into t values('李四','玩游戏,吃饭');
Query OK, 1 row affected (0.00 sec)
mysql> insert into t values('赵六','玩游戏,内卷');
Query OK, 1 row affected (0.00 sec)
mysql> insert into t values('陈七','玩游戏,写代码,吃饭,睡觉,内卷');
Query OK, 1 row affected (0.00 sec)
mysql> select * from t;
+--------+------------------------------------------+
| name | hobby |
+--------+------------------------------------------+
| 张三 | 玩游戏 |
| 李四 | 玩游戏,吃饭 |
| 赵六 | 玩游戏,内卷 |
| 陈七 | 写代码,玩游戏,吃饭,睡觉,内卷 |
+--------+------------------------------------------+
4 rows in set (0.00 sec)
那么我们可不可以和enum一样直接用数字插入呢?
mysql> insert into t values('赵日天',1);
Query OK, 1 row affected (0.00 sec)
mysql> insert into t values('赵日地',2);
Query OK, 1 row affected (0.00 sec)
mysql> insert into t values('秦始皇',3);
Query OK, 1 row affected (0.00 sec)
mysql> select * from t;
+-----------+------------------------------------------+
| name | hobby |
+-----------+------------------------------------------+
| 张三 | 玩游戏 |
| 李四 | 玩游戏,吃饭 |
| 赵六 | 玩游戏,内卷 |
| 陈七 | 写代码,玩游戏,吃饭,睡觉,内卷 |
| 赵日天 | 写代码 |
| 赵日地 | 玩游戏 |
| 秦始皇 | 写代码,玩游戏 |
+-----------+------------------------------------------+
7 rows in set (0.00 sec)
可以看到秦始皇的hobby是2个。
这是因为set采用数字插入的时候,采用的位图的方案,1代表001,2是010,3是011,所以秦始皇的写代码和玩游戏爱好都有,这也体现出了set数字插入的时候位图中的下标也是从1开始。
假如我们要查询喜欢写代码的人有哪些该如何做呢?
mysql> select * from t;
+-----------+------------------------------------------+
| name | hobby |
+-----------+------------------------------------------+
| 张三 | 玩游戏 |
| 李四 | 玩游戏,吃饭 |
| 赵六 | 玩游戏,内卷 |
| 陈七 | 写代码,玩游戏,吃饭,睡觉,内卷 |
| 赵日天 | 写代码 |
| 赵日地 | 玩游戏 |
| 秦始皇 | 写代码,玩游戏 |
+-----------+------------------------------------------+
7 rows in set (0.00 sec)
mysql> select * from t where hobby='写代码';
+-----------+-----------+
| name | hobby |
+-----------+-----------+
| 赵日天 | 写代码 |
+-----------+-----------+
1 row in set (0.00 sec)
这样查询显然不对,因为这是一种绝对查询,只会查询出爱好只有写代码的。
所以我们需要运用到一个叫find_in_set的函数。
find_in_set(sub,str_list) :如果 sub 在 str_list 中,则返回下标;如果不在,返回 0 ; str_list 用逗号分隔的字符串。
mysql> select * from t where find_in_set('写代码',hobby);
+-----------+------------------------------------------+
| name | hobby |
+-----------+------------------------------------------+
| 陈七 | 写代码,玩游戏,吃饭,睡觉,内卷 |
| 赵日天 | 写代码 |
| 秦始皇 | 写代码,玩游戏 |
+-----------+------------------------------------------+
3 rows in set (0.00 sec)
这样查询就对了,那么数字呢?
mysql> select * from t where find_in_set(1,hobby);
Empty set (0.00 sec)
mysql> select * from t where find_in_set(2,hobby);
Empty set (0.00 sec)
可见再通过位图数字查询是不可行了。