【MySQL】数据类型

文章目录

  • 1 :peach:数据类型分类:peach:
  • 2 :peach:数值类型:peach:
    • 2.1 :apple:tinyint类型:apple:
    • 2.2 :apple:bit类型:apple:
    • 2.3 :apple:小数类型:apple:
      • 2.3.1 :lemon:float:lemon:
      • 2.3.2 :lemon:decimal:lemon:
  • 3 :peach:字符串类型:peach:
    • 3.1 :apple:char:apple:
    • 3.2 :apple:varchar:apple:
    • 3.3 :apple:char和varchar比较:apple:
  • 4 :peach:日期和时间类型:peach:
  • 5 :peach:enum和set:peach:


1 数据类型分类

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


2 数值类型

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

2.1 tinyint类型

我们先创建一个只含有tinyint字段的表:
【MySQL】数据类型_第3张图片

我们往里面插入一些有效数据时:

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

mysql> insert into test1 values(-10);
Query OK, 1 row affected (0.01 sec)

mysql> select *from test1;
+------+
| num  |
+------+
|   10 |
|  -10 |
+------+
2 rows in set (0.00 sec)

当我们插入越界数据时;

mysql> insert into test1 values(128);
ERROR 1264 (22003): Out of range value for column 'num' at row 1
mysql> insert into test1 values(-129);
ERROR 1264 (22003): Out of range value for column 'num' at row 1
mysql> insert into test1 values(-200);
ERROR 1264 (22003): Out of range value for column 'num' at row 1

这里会报错,这跟我们C/C++语法不太一样,在C/C++语法中,超过了类型的最大范围后会发生截断,但是在MySQL中超过了该类型字段的最大范围后直接报错,这种严厉的规范其实是比较好的。

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

mysql> create table test2(num tinyint unsigned);
Query OK, 0 rows affected (0.02 sec)

mysql> desc test2;
+-------+---------------------+------+-----+---------+-------+
| Field | Type                | Null | Key | Default | Extra |
+-------+---------------------+------+-----+---------+-------+
| num   | tinyint(3) unsigned | YES  |     | NULL    |       |
+-------+---------------------+------+-----+---------+-------+
1 row in set (0.00 sec)

我们往里面插入一些负数时:

mysql> insert into test2 values(-1);
ERROR 1264 (22003): Out of range value for column 'num' at row 1
mysql> insert into test2 values(-5);
ERROR 1264 (22003): Out of range value for column 'num' at row 1

会直接报错,但是我们可以插入0或者在tinyint范围内的数据:

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

其他的数值类型也是同理只是范围不一样罢了,大家下去可自行验证。


2.2 bit类型

基本语法:

bit[(M)] : 位字段类型。M表示每个值的位数,范围从164。如果M被忽略,默认为1

举例:

 create table test3(id int,is_exit bit(8));

我们向test3里面插入下面的数据:

mysql> insert into test3 values(1,32);
Query OK, 1 row affected (0.01 sec)

mysql> insert into test3 values(2,64);
Query OK, 1 row affected (0.01 sec)

mysql> insert into test3 values(3,97);
Query OK, 1 row affected (0.00 sec)

【MySQL】数据类型_第4张图片
当我们查询时却发生了怪异的现象,为啥1中的is_exit显示不出来呢?这时因为bit类型显示默认都是以ASCII码的形式来显现,而ASCII码为32的字符是不可显字符。
我们再进行插入:

mysql> insert into test3 values(4,128);
Query OK, 1 row affected (0.01 sec)

mysql> insert into test3 values(5,256);
ERROR 1406 (22001): Data too long for column 'is_exit' at row 1
mysql> insert into test3 values(5,255);
Query OK, 1 row affected (0.01 sec)

发现255可以插入,但是256却不可以插入了,这是因为我们定义的bit类型最大为8个比特位,表示的最大范围为0 ~ 28-1(255)。


2.3 小数类型

2.3.1 float

语法:

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

案例:

小数:float(4,2)表示的范围是-99.99 ~ 99.99,MySQL在保存值时会进行四舍五入。

mysql> create table test4(num float(4,2));
Query OK, 0 rows affected (0.03 sec)

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

mysql> insert into test4 values(-99.99);
Query OK, 1 row affected (0.01 sec)

当我们插入下面数据时:

mysql> insert into test4 values(-99.994);
Query OK, 1 row affected (0.00 sec)

mysql> insert into test4 values(-99.995);
ERROR 1264 (22003): Out of range value for column 'num' at row 1

我们发现-99.994可以插入成功,但是-99.995却不可以插入成功,这是因为-99.994四舍五入后为-99.99,而-99.995四舍五入后超过了所定义的范围。

如果定义的是float(4,2) unsigned ,因为把它指定为无符号的数,范围是 0 ~ 99.99。

double的用法与float基本类似,这里就不再多讲解了。

2.3.2 decimal

语法:

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

decimal(5,2) 表示的范围是 -999.99 ~ 999.99
decimal(5,2) unsigned 表示的范围 0 ~ 999.99
decimal和float很像,但是有区别: float和decimal表示的精度不一样,比如下面:

mysql> insert into test5 values(10.12345678,10.12345678);
Query OK, 1 row affected (0.01 sec)

mysql> select* from test5;
+-------------+-------------+
| f1          | d1          |
+-------------+-------------+
| 10.12345695 | 10.12345678 |
+-------------+-------------+
1 row in set (0.00 sec)

我们发现使用decimal是更加精确的。因此如果我们希望某个数据表示高精度,选择decimal。
说明:

  • float表示的精度大约是7位。
  • decimal整数最大位数m为65。支持小数最大位数d是30。如果d被省略,默认为0。如果m被省略,
    默认是10。

3 字符串类型

3.1 char

语法:

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

注意上面指定的L是表示可以存储字符的长度,并不是字节。

3.2 varchar

语法:

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

案例:

mysql> create table test6(id int,str varchar(128));
Query OK, 0 rows affected (0.03 sec)

mysql> insert into test6 values(1,'我爱你');
Query OK, 1 row affected (0.01 sec)

mysql> insert into test6 values(2,'我爱你,中国');
Query OK, 1 row affected (0.01 sec)

mysql> insert into test6 values(3,'我爱你,中国人');
Query OK, 1 row affected (0.00 sec)

mysql> select* from test6;
+------+-----------------------+
| id   | str                   |
+------+-----------------------+
|    1 | 我爱你                |
|    2 | 我爱你,中国          |
|    3 | 我爱你,中国人        |
+------+-----------------------+
3 rows in set (0.00 sec)

说明:
关于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字节)。

3.3 char和varchar比较

【MySQL】数据类型_第5张图片如何选择定长或变长字符串?

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

4 日期和时间类型

常用的日期有如下三个:

  • 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 birthday (t1 date, t2 datetime, t3 timestamp);
Query OK, 0 rows affected (0.02 sec)

mysql> insert into birthday(t1,t2) values('1997-7-1','2008-8-8 12:1:1');
Query OK, 1 row affected (0.00 sec)

mysql> select *from birthday;
+------------+---------------------+---------------------+
| t1         | t2                  | t3                  |
+------------+---------------------+---------------------+
| 1997-07-01 | 2008-08-08 12:01:01 | 2023-08-18 15:08:48 |
+------------+---------------------+---------------------+
1 row in set (0.00 sec)

timestamp不需要我们自己填充。
当我们更新数据时:

mysql>  update birthday set t1='2000-1-1';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select* from birthday;
+------------+---------------------+---------------------+
| t1         | t2                  | t3                  |
+------------+---------------------+---------------------+
| 2000-01-01 | 2008-08-08 12:01:01 | 2023-08-18 15:10:51 |
+------------+---------------------+---------------------+
1 row in set (0.00 sec)

timestamp会自动更新到最新时间。


5 enum和set

语法:

enum:枚举,“单选”类型;
enum('选项1','选项2','选项3',...);
  • 该设定只是提供了若干个选项的值,最终一个单元格中,实际只存储了其中一个值;而且出于效率考虑,这些值实际存储的是“数字”,因为这些选项的每个选项值依次对应如下数字:1,2,3,…最多65535个;当我们添加枚举值时,也可以添加对应的数字编号。
set:集合,“多选”类型;
set('选项值1','选项值2','选项值3', ...);
  • 该设定只是提供了若干个选项的值,最终一个单元格中,设计可存储了其中任意多个值;而且出于效率考虑,这些值实际存储的是“数字”,因为这些选项的每个选项值依次对应如下字1,2,4,8,16,32,…最多64个。

说明:不建议在添加枚举值,集合值的时候采用数字的方式,因为不利于阅读。

案例:

mysql> create table hobby(
    -> gender enum('男','女'),
    -> hobby_sport set('羽毛球','乒乓球','篮球','排球','网球')
    -> );
Query OK, 0 rows affected (0.02 sec)

mysql> desc hobby;
+-------------+---------------------------------------------------------+------+-----+---------+-------+
| Field       | Type                                                    | Null | Key | Default | Extra |
+-------------+---------------------------------------------------------+------+-----+---------+-------+
| gender      | enum('男','女')                                         | YES  |     | NULL    |       |
| hobby_sport | set('羽毛球','乒乓球','篮球','排球','网球')             | YES  |     | NULL    |       |
+-------------+---------------------------------------------------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

当我们插入数据时:

mysql> insert into hobby values('男','羽毛球,篮球');
Query OK, 1 row affected (0.01 sec)

mysql> insert into hobby values('女','网球,排球');
Query OK, 1 row affected (0.00 sec)

mysql> select *from hobby;
+--------+------------------+
| gender | hobby_sport      |
+--------+------------------+
|| 羽毛球,篮球      |
|| 排球,网球        |
+--------+------------------+

我们甚至还可以使用数值来插入:

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

mysql> insert into hobby values(2,4);
Query OK, 1 row affected (0.01 sec)

mysql> insert into hobby values(2,11);
Query OK, 1 row affected (0.00 sec)

mysql> select* from hobby;
+--------+----------------------------+
| gender | hobby_sport                |
+--------+----------------------------+
|| 羽毛球,篮球                |
|| 排球,网球                  |
|| 羽毛球,乒乓球,篮球         |
|| 篮球                       |
|| 羽毛球,乒乓球,排球         |
+--------+----------------------------+
5 rows in set (0.00 sec)

其中值得注意的点是enum使用数值插入时,从1开始不断增加,而set则是用二进制来表示,不过注意二进制左边为低权值位,右边为高权值位,比如上面插入7,用二进制表示应该为00111,但是我们要将二进制颠倒过来变成11100 ,就表示(‘羽毛球’,‘乒乓球’,‘篮球’)。

假设我们向查询出喜欢篮球的人:

mysql> select * from hobby where hobby_sport='篮球';
+--------+-------------+
| gender | hobby_sport |
+--------+-------------+
|| 篮球        |
+--------+-------------+
1 row in set (0.00 sec)

我们发现只查询到了只喜欢打篮球的人,这明显不符合我们的预期,我们想要的是爱好有篮球的人,此时我们可以使用find_ in_ set函数。

find_in_set(sub,str_list) :如果 sub 在 str_list 中,则返回下标;如果不在,返回0;
str_list 用逗号分隔的字符串。
mysql> select find_in_set('a', 'a,b,c');
+---------------------------+
| find_in_set('a', 'a,b,c') |
+---------------------------+
|                         1 |
+---------------------------+
1 row in set (0.00 sec)

mysql> select find_in_set('d', 'a,b,c');
+---------------------------+
| find_in_set('d', 'a,b,c') |
+---------------------------+
|                         0 |
+---------------------------+
1 row in set (0.00 sec)

查询喜欢打篮球的人:

mysql> select * from hobby where find_in_set('篮球', hobby_sport);
+--------+----------------------------+
| gender | hobby_sport                |
+--------+----------------------------+
|| 羽毛球,篮球                |
|| 羽毛球,乒乓球,篮球         |
|| 篮球                       |
+--------+----------------------------+
3 rows in set (0.00 sec)


你可能感兴趣的:(MySQL,mysql,android,数据类型)