MySQL的数值类型
整数类型 | 字节 | 有符号 | 无符号 |
TINYINT | 1 | -128~+127 | 0~255 |
SAMLLINT | 2 | -32768~+32767 | 0~65535 |
MEDIUMINT | 3 | -8388608~+8388607 | 0~16777215 |
INT | 4 | -2147483648~+2147483647 | 0~4294967295 |
BIGINT | 8 | -9223372036854775808~+9223372036854775807 | 0~18446744073709551615 |
浮点数类型 | 字节 | 有符号 | 无符号 |
FLOAT | 4 | ||
DOUBLE | 8 |
定点数类型 | 字节 | 描述 |
DEC(M,D) | M+2 | 最大取值范围与DOUBLE相同。给定DEC的有效取值范围由M和D决定 |
注意:我们给定列属性之后,如果存取的数据超过类型范围的操作,会发生“Out of range”
zerofill关键字:
一般是配合整数类型来使用,表示用0填充的意思。也就是说在数字位数不够的空间用字符“0”来填充。
例如:
mysql> create table test1(
-> id int zerofill,
-> num int
-> );
Query OK, rows affected (0.02 sec) mysql> INSERT INTO test1 values(,);
Query OK, row affected (0.01 sec) mysql> SELECT * from test1;
+------------+------+
| id | num |
+------------+------+
| | | #我定义的id为11位整数,如果不够,就用字符“0”来填补。
+------------+------+
row in set (0.00 sec)
注意:我们一般会设置一个数据类型的宽度,比如像int(5)之类的,本来int类型的默认宽度是11位。那么当我们指定了宽度之后,再去存取大于5位的宽度的数据,是不会报错的。还是按照实际的精度进行保存的。
UNSIGNED属性:
所有的整数类型(浮点类型也有)的都有这样的一个属性。主要是用于需要在字段里面保存的数据是非负数或者保存有较大的上限值时。
当我们指定一个列为zerofill的时候,mysql默认加上UNSIGNED属性。
AUTO_INCREMENT属性:
所有的整数类型(只有整数类型有)都有一个AUTO_INCREMENT属性,它默认是从1开始计算,并以此加1。需要注意的是:
1、一个表中只能有一列有AUTO_INCREMENT这个属性。
2、当我们将一个列指定为AUTO_INCREMENT属性的时候这个列最好也要指定NOT NULL属性,当然最好再加上一个PRIMARY KEY属性或者UNIQUE会更好。否则当我们插入一个NULL给AUTO_INCREMENT这个列的时候,mysql默认为插入一个比该列中当前最大值大1的值。
小数
对于小数。mysql有两种表示:FLOAT和DOUBLE类型:单精度和双精度。
定点数
只有DECIMAL(DEC)一种表示。定点数在MYSQL内部以字符串形式存放,比浮点数更精确,适合用来存放货币等数据。
指定精度和标度。
可以使用FLOAT(M,N)格式指定精度和标度。M表示总共几位数字,N表示小数点后的位数。
mysql> CREATE TABLE test2( id1 FLOAT(5,2), id2 DOUBLE(5,2), id3 DECIMAL(5,2));
Query OK, 0 rows affected (0.04 sec) mysql> desc test2;
+-------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| id1 | float(5,2) | YES | | NULL | |
| id2 | double(5,2) | YES | | NULL | |
| id3 | decimal(5,2) | YES | | NULL | |
+-------+--------------+------+-----+---------+-------+
3 rows in set (0.00 sec) mysql> INSERT INTO test2 values(1.234,1.234,1.234);
Query OK, 1 row affected, 1 warning (0.00 sec) mysql> show warnings;
+-------+------+------------------------------------------+
| Level | Code | Message |
+-------+------+------------------------------------------+
| Note | 1265 | Data truncated for column 'id3' at row 1 | #对于dec定点类型,系统会报错
+-------+------+------------------------------------------+
1 row in set (0.00 sec) mysql> select * from test2;
+------+------+------+
| id1 | id2 | id3 |
+------+------+------+
| 1.23 | 1.23 | 1.23 |
+------+------+------+
1 row in set (0.00 sec)
总结:我们可以看出来float和double两个浮点类型,当指定的精度和标度的时候,MYSQL的保存值是会进行四舍五入的。比如上面的例子,我插入的数据精度过高,就只能以四舍五入的方式来存取了。对于DEC定点类型,我们上面的数据超越了精度和标度,系统反而报错了。
注意:浮点数后面跟(M,D)的用法不是数据库的标准用法,如果用于数据库的迁移,最好不要这么使用。
mysql> alter table test2 add column id4 float;
Query OK, 0 rows affected (0.06 sec)
Records: 0 Duplicates: 0 Warnings: 0 mysql> alter table test2 add column id5 double;
Query OK, 0 rows affected (0.06 sec)
Records: 0 Duplicates: 0 Warnings: 0 mysql> alter table test2 add column id6 decimal;
Query OK, 0 rows affected (0.19 sec)
Records: 0 Duplicates: 0 Warnings: 0 mysql> show columns from test2;
+-------+---------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------------+------+-----+---------+-------+
| id1 | float(5,2) | YES | | NULL | |
| id2 | double(5,2) | YES | | NULL | |
| id3 | decimal(5,2) | YES | | NULL | |
| id4 | float | YES | | NULL | |
| id5 | double | YES | | NULL | |
| id6 | decimal(10,0) | YES | | NULL | | #定点类型默认就是(10,0)
+-------+---------------+------+-----+---------+-------+
6 rows in set (0.00 sec) mysql> insert into test2 (id4,id5,id6) values (1.234,1.234,1.234);
Query OK, 1 row affected, 1 warning (0.00 sec) mysql> select id4,id5,id6 from test2 limit 1,1;
+-------+-------+------+
| id4 | id5 | id6 |
+-------+-------+------+
| 1.234 | 1.234 | 1 | #默认的定点类型只能保存整数部分,小数部分不能保存
+-------+-------+------+
1 row in set (0.00 sec)
总结:对于FLOAT和DOUBLE来说,浮点数如果不写精度和标度,则会按照实际精度值显示。比如上面的例子中,要插入数据是1.234,那么float和double保存的时候会按照数据原本的精度和标度来进行保存。但是定点数会按照默认值DECIMAL(10,0)来保存,所以上面的例子中定点类型的数据只能保存整数部分,小数部分被割舍了。
定点数如果不写精度和标度,则会按照默认值decimal(10.0)来进行操作。并且定点数据在指定精度和标度的情况下,如果数据超越了精度和标度值,系统则会报错。
一般我们的习惯就是,浮点类型的数据不加精度和标度,定点类型的数据要指定精度和标度。
日期时间类型
日期时间类型 | 字节 | 描述 |
DATE | 4 | "YYYY-MM-DD" |
TIME | 3 | "HH:MM:SS" |
DATETIME | 8 | "YYYY-MM-DD HH:MM:SS" |
TIMESTAMP | 4 | 14个字符表示 |
这几个的区别:
1、如果表示年月日,使用DATE
2、如果表示时分秒,使用TIME
3、如果表示年月日时分秒,使用DTAETIME
4、如果需要经常插入或者更新日期为当前系统时间,则使用TIMESTAMP表示。TIMESTAMP值返回的结果则是“”YYYY-MM-DD HH:MM:SS”的格式来显示。
5、每种日期类型都有一定的有效值范围,如果超出范围,系统会提示错误,并用零值来填充。
例子演示:
mysql> create table test3(
-> d DATE,
-> d2 TIME,
-> d3 DATETIME
-> )
-> ;
Query OK, 0 rows affected (0.02 sec) mysql> desc test3;
+-------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+-------+
| d | date | YES | | NULL | |
| d2 | time | YES | | NULL | |
| d3 | datetime | YES | | NULL | |
+-------+----------+------+-----+---------+-------+
3 rows in set (0.00 sec) mysql> insert into test3 values(now(),now(),now());
Query OK, 1 row affected, 1 warning (0.00 sec) mysql> select *from test3;
+------------+----------+---------------------+
| d | d2 | d3 |
+------------+----------+---------------------+
| 2018-10-23 | 12:55:22 | 2018-10-23 12:55:22 |
+------------+----------+---------------------+
1 row in set (0.00 sec)
TIMESTAMP演示:
mysql> create table test4(
-> d TIMESTAMP
-> );
Query OK, 0 rows affected (0.02 sec) mysql> insert into test4 values(now());
Query OK, 1 row affected (0.00 sec) mysql> select * from test4;
+---------------------+
| d |
+---------------------+
| 2018-10-23 12:57:45 |
+---------------------+
1 row in set (0.00 sec) mysql> desc test4;
+-------+-----------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-----------+------+-----+-------------------+-----------------------------+
| d | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
+-------+-----------+------+-----+-------------------+-----------------------------+
1 row in set (0.00 sec)
总结:我们发现当给一个列值创建TIMESTAMP属性的时候,mysql自动就会给该列值默认的属性“CURRENT_TIMESTAMP”。当我们读取数据的时候,系统存取的是时间戳格式,但是返回的结果会格式化为“DATETIME”格式。
现在我们尝试在一个表中创建两个时间戳属性的列
mysql> alter table test4 add column d2 TIMESTAMP;
Query OK, 0 rows affected (0.07 sec)
Records: 0 Duplicates: 0 Warnings: 0 mysql> desc test4;
+-------+-----------+------+-----+---------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-----------+------+-----+---------------------+-----------------------------+
| d | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
| d2 | timestamp | NO | | 0000-00-00 00:00:00 | |
+-------+-----------+------+-----+---------------------+-----------------------------+
2 rows in set (0.00 sec)
这个时候我们发现第二个时间戳类型的列没有了“CURRENT_TIMESTAMP”属性,默认值是“0”。
总结:mysql只会给表中第一个TIMESTAMP字段设置默认值为系统日期“CURRENT_TIMESTAMP”,第二个TIMESTAMP字段则自动设置为0。
MYSQL的TIMESTAMP属性与DTAETIME的属性还有一些区别,详细的我们可以参考书籍深入浅出mysql第63页。
字符串类型
CHAR和VARCHAR类型的区别:
存储上来说:
CHAR列的长度固定为创建表时声明的长度。而varchar列中的值为可变长字符串。varchar中实际存储的是实际的字符串长度再加上一个记录字符串长度的字节。
varchar(M)和char(M),M表示字节数,char最多可以放入255个字节,而varchar最多可以放入65535个字节。
在mysql5.7中,如果插入的字符串长度超过指定的长度,默认会报错。
检索数据来说:
假如说插入的数据尾部含有空格,那么检索数据的时候,CHAR列删除了尾部的空格,而varchar则保留这些空格。
例子:
mysql> create table test6(
-> v char(4),
-> c varchar(4)
-> );
Query OK, 0 rows affected (0.02 sec) mysql> insert into test6 values ('ab ','ab '); #在每个字符串后面添加两个空格。
Query OK, 1 row affected (0.06 sec) mysql> select concat(v,'+'),concat(c,'+') from test6;
+---------------+---------------+
| concat(v,'+') | concat(c,'+') |
+---------------+---------------+
| ab+ | ab + |
+---------------+---------------+
1 row in set (0.00 sec)
CHAR列最后的空格在做操作时已经被删除,而VARCHAR列依然保留空格。
ENUM类型
枚举类型
例子:
mysql> create table test7(
-> gender enum('M','F')
-> );
Query OK, 0 rows affected (0.02 sec) mysql> insert into test7 values ('M'),('m'),('F');
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0 mysql> select * from test7;
+--------+
| gender |
+--------+
| M |
| M |
| F |
+--------+
总结:枚举类型就是我们在创建表的时候就定义好枚举类型的成员,插入数据的时候从枚举成员中插入。可以看出来,枚举类型是不区分大小写的。
如果将ENUM列声明为允许NULL,NULL值则为该列的一个有效值,并且 默认值为NULL。如果ENUM列被声明为NOTNULL,其默认值为允许的值列的第1个元素。