MySQL 数据类型

Posted 小白°

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL 数据类型相关的知识,希望对你有一定的参考价值。

介绍

存储引擎决定了表的类型,而表存放的数据也要有不同的类型,每种数据类型都有自己的宽度,但宽度是可选的

详细参考链接:http://www.runoob.com/mysql/mysql-data-types.html

#数字
    整型:tinyint int bigint
    
    小数:
        float:在位数比较短的情况下不精准
        double:在位数比较长的情况下不精准
        0.000001230123123123
            存成:0.000001230000
        decimal:(如果用小数,则用推荐使用decimal)
            精准
            内部原理是以字符串形式去存
#字符串:
    char(10):简单粗暴,浪费空间,存取速度快
            root存成root000000
    varchar:精准,节省空间,存取速度慢

    sql优化:创建表时,定长的类型往前放,变长的往后放
                    比如性别           比如地址或描述信息

    >255个字符,超了就把文件路径存放到数据库中。
            比如图片,视频等找一个文件服务器,数据库中只存路径或url。


#3. 时间类型:
    最常用:datetime


#4. 枚举类型与集合类型
   enum 和set

一、数值类型

整数类型:tinyint smallint mediumint int bigint

作用:存储年龄,等级,id,各种好吗等

 

========================================
        tinyint[(m)] [unsigned] [zerofill]

            小整数,数据类型用于保存一些范围的整数数值范围:
            有符号:
                -128 ~ 127
            无符号:
                0 ~ 255

            PS: mysql中无布尔值,使用tinyint(1)构造。



========================================
        int[(m)][unsigned][zerofill]

            整数,数据类型用于保存一些范围的整数数值范围:
            有符号:
                    -2147483648 ~ 2147483647
            无符号:
                    0 ~ 4294967295



========================================
        bigint[(m)][unsigned][zerofill]
            大整数,数据类型用于保存一些范围的整数数值范围:
            有符号:
                    -9223372036854775808 ~ 9223372036854775807
            无符号:
                    0  ~  18446744073709551615

验证1:有符号和无符号tinyint

============有符号tinyint==============
# 创建数据库db4
create database db4 charset utf8;

# 切换到当前db4数据库
mysql> use db4;

# 创建t1 规定x字段为tinyint数据类型(默认是有符号的)
mysql> create table t1(x tinyint);

# 验证,插入-1这个数
mysql>   insert into t1 values(-1);

# 查询 表记录,查询成功(证明默认是有符号类型)
mysql> select * from t1;
+------+
| x    |
+------+
| -1 |
+------+

#执行如下操作,会发现报错。因为有符号范围在(-128,127)
mysql>   insert into t1 values(-129),(128);
ERROR 1264 (22003): Out of range value for column \'x\' at row 1


============无符号tinyint==============
# 创建表时定义记录的字符为无符号类型(0,255) ,使用unsigned
mysql> create table t2(x tinyint unsigned);

# 报错,超出范围
mysql>   insert into t2 values(-129);
ERROR 1264 (22003): Out of range value for column \'x\' at row 1

# 插入成功
mysql>   insert into t2 values(255);
Query OK, 1 row affected (0.00 sec)

 

 验证2:int类型后面的存储是显示宽度,而不是存储宽度

mysql> create table t3(id int(1) unsigned);

#插入255555记录也是可以的
mysql> insert into t3 values(255555);

mysql> select * from t3;
+--------+
| id     |
+--------+
| 255555 |
+--------+
ps:以上操作还不能够验证,再来一张表验证用zerofill 用0填充

# zerofill 用0填充
mysql> create table t4(id int(5) unsigned zerofill);


mysql> insert into t4 value(1);
Query OK, 1 row affected (0.00 sec)

#插入的记录是1,但是显示的宽度是00001
mysql> select * from t4;
+-------+
| id    |
+-------+
| 00001 |
+-------+
1 row in set (0.00 sec)

注意:为该类型指定宽度时,仅仅只是指定查询结果的显示宽度,与存储范围无关,存储范围如下

其实我们完全没必要为整数类型指定显示宽度,使用默认的就可以了

默认的显示宽度,都是在最大值的基础上加1

int的存储宽度是4个Bytes,即32个bit,即2**32

无符号最大值为:4294967296-1

有符号最大值:2147483648-1

有符号和无符号的最大数字需要的显示宽度均为10,而针对有符号的最小值则需要11位才能显示完全,所以int类型默认的显示宽度为11是非常合理的

最后:整形类型,其实没有必要指定显示宽度,使用默认的就ok

 二、浮点型

定点数类型: DEC等同于DECIMAL

浮点类型:FLOAT DOUBLE

作用:存储薪资、身高、体重、体质参数等

语法:

-------------------------FLOAT-------------------
FLOAT[(M,D)] [UNSIGNED] [ZEROFILL]
#参数解释:单精度浮点数(非准确小数值),M是全长,D是小数点后个数。M最大值为255,D最大值为30

#有符号:
           -3.402823466E+38 to -1.175494351E-38,
           1.175494351E-38 to 3.402823466E+38

#无符号:
           1.175494351E-38 to 3.402823466E+38
#精确度: 
           **** 随着小数的增多,精度变得不准确 ****


 -------------------------DOUBLE-----------------------
DOUBLE[(M,D)] [UNSIGNED] [ZEROFILL]

#参数解释: 双精度浮点数(非准确小数值),M是全长,D是小数点后个数。M最大值为255,D最大值为30

#有符号:
           -1.7976931348623157E+308 to -2.2250738585072014E-308
           2.2250738585072014E-308 to 1.7976931348623157E+308

#无符号:
           2.2250738585072014E-308 to 1.7976931348623157E+308

#精确度:
           ****随着小数的增多,精度比float要高,但也会变得不准确 ****

======================================
--------------------DECIMAL------------------------
decimal[(m[,d])] [unsigned] [zerofill]

#参数解释:准确的小数值,M是整数部分总个数(负号不算),D是小数点后个数。 M最大值为65,D最大值为30。


#精确度:
           **** 随着小数的增多,精度始终准确 ****
           对于精确数值计算时需要用此类型
           decaimal能够存储精确值的原因在于其内部按照字符串存储。

 

验证三种类型建表:

#1验证FLOAT类型建表:
mysql> create table t5(x float(256,31));
ERROR 1425 (42000): Too big scale 31 specified for column \'x\'. Maximum is 30.
mysql> create table t5(x float(256,30));
ERROR 1439 (42000): Display width out of range for column \'x\' (max = 255)
mysql> create table t5(x float(255,30)); #建表成功
Query OK, 0 rows affected (0.03 sec)

#2验证DOUBLE类型建表:
mysql> create table t6(x double(255,30)); #建表成功
Query OK, 0 rows affected (0.03 sec)

#3验证deimal类型建表:
mysql> create table t7(x decimal(66,31));
ERROR 1425 (42000): Too big scale 31 specified for column \'x\'. Maximum is 30.
mysql> create table t7(x decimal(66,30));
ERROR 1426 (42000): Too big precision 66 specified for column \'x\'. Maximum is 65.
mysql> create table t7(x decimal(65,30)); #建表成功
Query OK, 0 rows affected (0.00 sec)

 

验证三种类型的精度

# 分别对三张表插入相应的记录
mysql> insert into t5 values(1.1111111111111111111111111111111);#小数点后31个1
Query OK, 1 row affected (0.01 sec)

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

mysql> insert into t7 values(1.1111111111111111111111111111111);
Query OK, 1 row affected, 1 warning (0.00 sec)

# 查询结果
mysql> select * from t5; #随着小数的增多,精度开始不准确
+----------------------------------+
| x                                |
+----------------------------------+
| 1.111111164093017600000000000000 |
+----------------------------------+
1 row in set (0.00 sec)

mysql> select * from t6; #精度比float要准确点,但随着小数的增多,同样变得不准确
+----------------------------------+
| x                                |
+----------------------------------+
| 1.111111111111111200000000000000 |
+----------------------------------+
1 row in set (0.00 sec)

mysql> select * from t7; #精度始终准确,d为30,于是只留了30位小数
+----------------------------------+
| x                                |
+----------------------------------+
| 1.111111111111111111111111111111 |
+----------------------------------+
1 row in set (0.00 sec)

 

三、日期类型

DATE TIME DATETIME TIMESTAMP YEAR
作用:存储用户注册时间,文章发布时间,员工入职时间,出生时间,过期时间等

语法:
        YEAR
            YYYY(1901/2155)

        DATE
            YYYY-MM-DD(1000-01-01/9999-12-31)

        TIME
            HH:MM:SS(\'-838:59:59\'/\'838:59:59\')

        DATETIME

            YYYY-MM-DD HH:MM:SS(1000-01-01 00:00:00/9999-12-31 23:59:59    Y)

        TIMESTAMP

            YYYYMMDD HHMMSS(1970-01-01 00:00:00/2037 年某时)

 

验证:

1、year

mysql> create table t8(born_year year);#无论year指定何种宽度,最后都默认是year(4)
Query OK, 0 rows affected (0.03 sec)

#插入失败,超出范围(1901/2155)
mysql>  insert into t8 values
    ->  (1900),
    -> (1901),
    ->  (2155),
    ->  (2156);
ERROR 1264 (22003): Out of range value for column \'born_year\' at row 1


mysql> select * from t8;
Empty set (0.01 sec)


mysql> insert into t8 values
    -> (1905),
    -> (2018);
Query OK, 2 rows affected (0.00 sec) #插入记录成功
Records: 2  Duplicates: 0  Warnings: 0


mysql> select * from t8;
+-----------+
| born_year |
+-----------+
|      1905 |
|      2018 |
+-----------+
2 rows in set (0.00 sec)

 

 

2、date、year、datetime

#创建t9表
mysql> create table t9(d date,t time,dt datetime);
Query OK, 0 rows affected (0.06 sec)

#查看表的结构
mysql> desc t9;
+-------+----------+------+-----+---------+-------+
| Field | Type     | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+-------+
| d     | date     | YES  |     | NULL    |       |
| t     | time     | YES  |     | NULL    |       |
| dt    | datetime | YES  |     | NULL    |       |
+-------+----------+------+-----+---------+-------+
3 rows in set (0.14 sec)


# 调用mysql自带的now()函数,获取当前类型指定的时间 如下结构
mysql> insert into t9 values(now(),now(),now());
Query OK, 1 row affected, 1 warning (0.01 sec)

mysql> select * from t9;
+------------+----------+---------------------+
| d          | t        | dt                  |
+------------+----------+---------------------+
| 2018-06-09 | 09:35:20 | 2018-06-09 09:35:20 |
+------------+----------+---------------------+
1 row in set (0.00 sec)

 

 

3、timestamp(了解即可)

mysql>  create table t10(time timestamp);
Query OK, 0 rows affected (0.06 sec)

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

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

mysql>  select * from t10;
+------+
| time |
+------+
| NULL |
| NULL |
+------+

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

mysql> select * from t10;
+---------------------+
| time                |
+---------------------+
| 2018-06-09 09:44:48 |
+---------------------+
1 row in set (0.01 sec)

  

datetime与timestamp的区别

在实际应用的很多场景中,MySQL的这两种日期类型都能够满足我们的需要,存储精度都为秒,但在某些情况下,会展现出他们各自的优劣。
下面就来总结一下两种日期类型的区别。

1.DATETIME的日期范围是1001——9999年,TIMESTAMP的时间范围是1970——2038年。

2.DATETIME存储时间与时区无关,TIMESTAMP存储时间与时区有关,显示的值也依赖于时区。在mysql服务器,
操作系统以及客户端连接都有时区的设置。

3.DATETIME使用8字节的存储空间,TIMESTAMP的存储空间为4字节。因此,TIMESTAMP比DATETIME的空间利用率更高。

4.DATETIME的默认值为null;TIMESTAMP的字段默认不为空(not null),默认值为当前时间(CURRENT_TIMESTAMP),
如果不做特殊处理,并且update语句中没有指定该列的更新值,则默认更新为当前时间。

 

 

注意事项

============注意啦,注意啦,注意啦===========
#1. 单独插入时间时,需要以字符串的形式,按照对应的格式插入
#2. 插入年份时,尽量使用4位值
#3. 插入两位年份时,<=69,以20开头,比如50,  结果2050      
                >=70,以19开头,比如71,结果1971
 create table t12(y year);
 insert into t12 values  (50),(71);
 select * from t12;
+------+
| y    |
+------+
| 2050 |
| 1971 |
+------+

 

 

综合练习:

创建一张学生表(student),要求有id,姓名,出生年份,出生的年月日,进班的时间,以及来老男孩学习的现在具体时间。

mysql> create table student(
    -> id int,
    -> name varchar(20),
    -> born_year year,
    -> birth date,
    -> class_time time,
    -> reg_time datetime
    -> );
Query OK, 0 rows affected (0.02 sec)

mysql> insert into student values
    ->   (1,\'alex\',"1995","1995-11-11","11:11:11","2017-11-11 11:11:11"),
    ->   (2,\'egon\',"1997","1997-12-12","12:12:12","2017-12-12 12:12:12"),
    ->   (3,\'wsb\',"1998","1998-01-01","13:13:13","2017-01-01 13:13:13");
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql>   select * from student;
+------+------+-----------+------------+------------+---------------------+
| id   | name | born_year | birth      | class_time | reg_time            |
+------+------+-----------+------------+------------+---------------------+
|    1 | alex |      1995 | 1995-11-11 | 11:11:11   | 2017-11-11 11:11:11 |
|    2 | egon |      1997 | 1997-12-12 | 12:12:12   | 2017-12-12 12:12:12 |
|    3 | wsb  |      1998 | 1998-01-01 | 13:13:13   | 2017-01-01 13:13:13 |
+------+------+-----------+------------+------------+---------------------+
3 rows in set (0.00 sec)

 

 

四、字符类型

#官网:https://dev.mysql.com/doc/refman/5.7/en/char.html
#注意:char和varchar括号内的参数指的都是字符的长度

#char类型:定长,简单粗暴,浪费空间,存取速度快
    字符长度范围:0-255(一个中文是一个字符,是utf8编码的3个字节)
    存储:
        存储char类型的值时,会往右填充空格来满足长度
        例如:指定长度为10,存>10个字符则报错,存<10个字符则用空格填充直到凑够10个字符存储

    检索:
        在检索或者说查询时,查出的结果会自动删除尾部的空格,除非我们打开pad_char_to_full_length SQL模式(设置SQL模式:SET sql_mode = \'PAD_CHAR_TO_FULL_LENGTH\';
      查询sql的默认模式:select @@sql_mode;)

#varchar类型:变长,精准,节省空间,存取速度慢
    字符长度范围:0-65535(如果大于21845会提示用其他类型 。mysql行最大限制为65535字节,字符编码为utf-8:https://dev.mysql.com/doc/refman/5.7/en/column-count-limit.html)
    存储:
        varchar类型存储数据的真实内容,不会用空格填充,如果\'ab  \',尾部的空格也会被存起来
        强调:varchar类型会在真实数据前加1-2Bytes的前缀,该前缀用来表示真实数据的bytes字节数(1-2Bytes最大表示65535个数字,正好符合mysql对row的最大字节限制,即已经足够使用)
        如果真实的数据<255bytes则需要1Bytes的前缀(1Bytes=8bit 2**8最大表示的数字为255)
        如果真实的数据>255bytes则需要2Bytes的前缀(2Bytes=16bit 2**16最大表示的数字为65535)

    检索:
        尾部有空格会保存下来,在检索或者说查询时,也会正常显示包含空格在内的内容

 

官网解释如下:

验证:

验证之前了解两个函数:

length():查看字节数
char_length():查看字符数

1.char填充空格来满足固定长度,但是在查询时却会很不要脸地删除尾部的空格(装作自己好像没有浪费过空间一样),然后修改sql_mode让其现出原形。

# 创建t1表,分别指明字段x为char类型,字段y为varchar类型
mysql> create table t1(x char(5),y varchar(4));
Query OK, 0 rows affected (0.16 sec)

# char存放的是5个字符,而varchar存4个字符
mysql>  insert into t1 values(\'你瞅啥 \',\'你瞅啥 \');
Query OK, 1 row affected (0.01 sec)

# 在检索时char很不要脸地将自己浪费的2个字符给删掉了,装的好像自己没浪费过空间一样,而varchar很老实,存了多少,就显示多少
mysql> select x,char_length(x),y,char_length(y) from t1;
+-----------+----------------+------------+----------------+
| x         | char_length(x) | y          | char_length(y) |
+-----------+----------------+------------+----------------+
| 你瞅啥    |              3 | 你瞅啥     |              4 |
+-----------+----------------+------------+----------------+
1 row in set (0.02 sec)

 #略施小计,让char现原形
 mysql> SET sql_mode = \'PAD_CHAR_TO_FULL_LENGTH\';
Query OK, 0 rows affected (0.00 sec)

#查看当前mysql的mode模式
mysql> select @@sql_mode;
+-------------------------+
| @@sql_mode              |
+-------------------------+
| PAD_CHAR_TO_FULL_LENGTH |
+-------------------------+
1 row in set (0.00 sec)

#原形毕露了吧。。。。
mysql> select x,char_length(x) y,char_length(y) from t1;
+-------------+------+----------------+
| x           | y    | char_length(y) |
+-------------+------+----------------+
| 你瞅啥      |    5 |              4 |
+-------------+------+----------------+
1 row in set (0.00 sec)

# 查看字节数
#char类型:3个中文字符+2个空格=11Bytes
#varchar类型:3个中文字符+1个空格=10Bytes
mysql> select x,length(x),y,length(y) from t1;
+-------------+-----------+------------+-----------+
| x           | length(x) | y          | length(y) |
+-------------+-----------+------------+-----------+
| 你瞅啥      |        11 | 你瞅啥     |        10 |
+-------------+-----------+------------+-----------+
1 row in set (0.02 sec)

 

总结:

#常用字符串系列:char与varchar
注:虽然varchar使用起来较为灵活,但是从整个系统的性能角度来说,char数据类型的处理速度更快,有时甚至可以超出varchar处理速度的50%。因此,用户在设计数据库时应当综合考虑各方面的因素,以求达到最佳的平衡

#其他字符串系列(效率:char>varchar>text)
TEXT系列 TINYTEXT TEXT MEDIUMTEXT LONGTEXT
BLOB 系列    TINYBLOB BLOB MEDIUMBLOB LONGBLOB 
BINARY系列 BINARY VARBINARY

text:text数据类型用于保存变长的大字符串,可以组多到65535 (2**16 − 1)个字符。
mediumtext:A TEXT column with a maximum length of 16,777,215 (2**24 − 1) characters.
longtext:A TEXT column with a maximum length of 4,294,967,295 or 4GB (2**32 − 1) characters.

 

五、枚举和集合类型

字段的值只能在给定范围中选择,如单选框,多选框

enum 单选 只能在给定的范围内选一个值,如性别 sex 男male/女female

set 多选 在给定的范围内可以选择一个或一个以上的值(爱好1,爱好2,爱好3...)

mysql> create table consumer(
    -> id int,
    -> name varchar(50),
    -> sex enum(\'male\',\'female\',\'other\'),
    -> level enum(\'vip1\',\'vip2\',\'vip3\',\'vip4\'),#在指定范围内,多选一
    -> fav set(\'play\',\'music\',\'read\',\'study\') #在指定范围内,多选多
    -> );
Query OK, 0 rows affected (0.03 sec)


mysql> insert into consumer values
    -> (1,\'赵云\',\'male\',\'vip2\',\'read,study\'),
    -> (2,\'赵云2\',\'other\',\'vip4\',\'play\');
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> select * from consumer;
+------+---------+-------+-------+------------+
| id   | name    | sex   | level | fav        |
+------+---------+-------+-------+------------+
|    1 | 赵云    | male  | vip2  | read,study |
|    2 | 赵云2   | other | vip4  | play       |
+------+---------+-------+-------+------------+
2 rows in set (0.00 sec)

 

以上是关于MySQL 数据类型的主要内容,如果未能解决你的问题,请参考以下文章

在代码片段中包含类型转换

对这个带有 & 不带 = 的代码片段返回类型感到非常困惑

从mysql的片段中加载ListView

硬核!管理mysql数据库的工具

对“xxx”类型的已垃圾回收委托进行了回调。这可能会导致应用程序崩溃损坏和数据丢失。向非托管代码传递委托时,托管应用程序必须让这些委托保持活动状态,直到确信不会再次调用它们。 错误解决一例。(代码片段

连接MySQL出现错误:ERROR 1045 (28000): Access denied for user ‘root‘@‘localhost‘ (using password: YES)(代码片段