mysql三-2:数据类型
一、介绍
存储引擎决定了表的类型,而表内存放的数据也要有不同的类型,每种数据类型都有自己的宽度,但宽度是可选的
详细参考:
- http://www.runoob.com/mysql/mysql-data-types.html
- http://dev.mysql.com/doc/refman/5.7/en/data-type-overview.html
mysql常用数据类型概览
#1. 数字: 整型:tinyinit int bigint 小数: float :在位数比较短的情况下不精准 double :在位数比较长的情况下不精准 0.000001230123123123 存成:0.000001230000 decimal:(如果用小数,则用推荐使用decimal) 精准 内部原理是以字符串形式去存 #2. 字符串: char(10):简单粗暴,浪费空间,存取速度快 root存成root000000 varchar:精准,节省空间,存取速度慢 sql优化:创建表时,定长的类型往前放,变长的往后放 比如性别 比如地址或描述信息 >255个字符,超了就把文件路径存放到数据库中。 比如图片,视频等找一个文件服务器,数据库中只存路径或url。 #3. 时间类型: 最常用:datetime #4. 枚举类型与集合类型
二、数值类型
1、整数类型: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
=========有符号和无符号tinyint========== #tinyint默认为有符号 MariaDB [db1]> create table t1(x tinyint); #默认为有符号,即数字前有正负号 MariaDB [db1]> desc t1; MariaDB [db1]> insert into t1 values -> (-129), -> (-128), -> (127), -> (128); MariaDB [db1]> select * from t1; +------+ | x | +------+ | -128 | #-129存成了-128 | -128 | #有符号,最小值为-128 | 127 | #有符号,最大值127 | 127 | #128存成了127 +------+ #设置无符号tinyint MariaDB [db1]> create table t2(x tinyint unsigned); MariaDB [db1]> insert into t2 values -> (-1), -> (0), -> (255), -> (256); MariaDB [db1]> select * from t2; +------+ | x | +------+ | 0 | -1存成了0 | 0 | #无符号,最小值为0 | 255 | #无符号,最大值为255 | 255 | #256存成了255 +------+ ============有符号和无符号int============= #int默认为有符号 MariaDB [db1]> create table t3(x int); #默认为有符号整数 MariaDB [db1]> insert into t3 values -> (-2147483649), -> (-2147483648), -> (2147483647), -> (2147483648); MariaDB [db1]> select * from t3; +-------------+ | x | +-------------+ | -2147483648 | #-2147483649存成了-2147483648 | -2147483648 | #有符号,最小值为-2147483648 | 2147483647 | #有符号,最大值为2147483647 | 2147483647 | #2147483648存成了2147483647 +-------------+ #设置无符号int MariaDB [db1]> create table t4(x int unsigned); MariaDB [db1]> insert into t4 values -> (-1), -> (0), -> (4294967295), -> (4294967296); MariaDB [db1]> select * from t4; +------------+ | x | +------------+ | 0 | #-1存成了0 | 0 | #无符号,最小值为0 | 4294967295 | #无符号,最大值为4294967295 | 4294967295 | #4294967296存成了4294967295 +------------+ ==============有符号和无符号bigint============= MariaDB [db1]> create table t6(x bigint); MariaDB [db1]> insert into t5 values -> (-9223372036854775809), -> (-9223372036854775808), -> (9223372036854775807), -> (9223372036854775808); MariaDB [db1]> select * from t5; +----------------------+ | x | +----------------------+ | -9223372036854775808 | | -9223372036854775808 | | 9223372036854775807 | | 9223372036854775807 | +----------------------+ MariaDB [db1]> create table t6(x bigint unsigned); MariaDB [db1]> insert into t6 values -> (-1), -> (0), -> (18446744073709551615), -> (18446744073709551616); MariaDB [db1]> select * from t6; +----------------------+ | x | +----------------------+ | 0 | | 0 | | 18446744073709551615 | | 18446744073709551615 | +----------------------+ ======用zerofill测试整数类型的显示宽度============= MariaDB [db1]> create table t7(x int(3) zerofill); MariaDB [db1]> insert into t7 values -> (1), -> (11), -> (111), -> (1111); MariaDB [db1]> select * from t7; +------+ | x | +------+ | 001 | | 011 | | 111 | | 1111 | #超过宽度限制仍然可以存 +------+
5.7版本mysql,在插入数据超出数据类型范围时,直接报错。
注意:为该类型指定宽度时,仅仅只是指定查询结果的显示宽度,与存储范围无关,存储范围如下
其实我们完全没必要为整数类型指定显示宽度,使用默认的就可以了
默认的显示宽度,都是在最大值的基础上加1
显示宽度和存储宽度区分:所有类型的存储宽度都已经固定死了,能够修改的仅仅只是显示宽度。
int的存储宽度是4个Bytes,即32个bit,即2**32
无符号最大值为:4294967296-1
有符号最大值:2147483648-1
有符号和无符号的最大数字需要的显示宽度均为10,而针对有符号的最小值则需要11位(加上负号)才能显示完全,所以int类型默认的显示宽度为11是非常合理的。
最后:整形类型,其实没有必要指定显示宽度,使用默认的就ok。而除了整型类型外,其他数据类型的宽度就是存储宽度。
2、浮点型
定点数类型DEC等同于DECIMAL
浮点类型:FLOAT DOUBLE
作用:存储薪资、身高、体重、体质参数等。
(1)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
精确度:随着小数的增多,精度变得不准确
(2)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高,但也会变得不准确。
(3)decimal[(m[,d])] [unsigned] [zerofill]
定义:准确的小数值,m是数字总个数(负号不算),d是小数点后个数。m最大值为65,d最大值为30.
精确度:随着小数的增多,精度始终准确。
对于精确计算时需要使用此类型。decimal能够存储精确值的原因在于其内部按照字符串存储。
缺点:数字总个数只有65.
mysql> create table t8(x float(255,30)); Query OK, 0 rows affected (0.01 sec) mysql> create table t9(x double(255,30)); Query OK, 0 rows affected (0.01 sec) mysql> create table t10(x decimal(65,30)); Query OK, 0 rows affected (0.02 sec) mysql> mysql> insert into t8 values(1.111111111111111111111111111111); Query OK, 1 row affected (0.00 sec) mysql> insert into t9 values(1.111111111111111111111111111111); Query OK, 1 row affected (0.00 sec) mysql> insert into t10 values(1.111111111111111111111111111111); Query OK, 1 row affected (0.00 sec) mysql> select * from t8; # 随着小数的增多,精度下降 +----------------------------------+ | x | +----------------------------------+ | 1.111111164093017600000000000000 | +----------------------------------+ 1 row in set (0.00 sec) mysql> select * from t9; # 精度也会下降,比float强一点 +----------------------------------+ | x | +----------------------------------+ | 1.111111111111111200000000000000 | +----------------------------------+ 1 row in set (0.00 sec) mysql> select * from t10; # 精度始终准确 +----------------------------------+ | x | +----------------------------------+ | 1.111111111111111111111111111111 | +----------------------------------+ 1 row in set (0.00 sec)
三、日期类型
日期类型:DATE TIME DATETIME TIMESTAMP YEAR
作用:存储用户注册时间,文章发布时间,员工入职时间,出生时间,过期时间等。
1、各种日期类型的时间范围
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 年某时)
mysql> create table student( -> id int, -> name char(6), # 存储宽度 -> born_year year, # YEAR类型 -> birth_date date, # DATE类型 -> class_time time, # TIME类型 -> reg_time datetime # DATETIME类型 -> ); Query OK, 0 rows affected (0.01 sec) mysql> insert into student values -> (1, 'egon', now(), now(), now(),now()); Query OK, 1 row affected, 1 warning (0.00 sec) mysql> select * from student; +------+------+-----------+------------+------------+---------------------+ | id | name | born_year | birth_date | class_time | reg_time | +------+------+-----------+------------+------------+---------------------+ | 1 | egon | 2018 | 2018-05-10 | 16:13:49 | 2018-05-10 16:13:49 | +------+------+-----------+------------+------------+---------------------+ 1 row in set (0.00 sec)
mysql> insert into student values
-> (2, 'alex', '1988', '1988-1-12', '12:12:12', "2017-12-12 12:12:12"); # 注意是分号结束
Query OK, 1 row affected (0.00 sec)
mysql> select * from student;
+------+------+-----------+------------+------------+---------------------+
| id | name | born_year | birth_date | class_time | reg_time |
+------+------+-----------+------------+------------+---------------------+
| 1 | egon | 2018 | 2018-05-10 | 16:13:49 | 2018-05-10 16:13:49 |
| 2 | alex | 1988 | 1988-01-12 | 12:12:12 | 2017-12-12 12:12:12 |
+------+------+-----------+------------+------------+---------------------+
2 rows in set (0.00 sec
在多行输入时,如果发现输入错误想取消当前输入,可以在当前行输入“\c”,如果前面有一个引号,可以在\c前加一个对应的引号。
2、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语句中没有指定该列的更新值,则默认更新为当前时间。
总结相对于节省的一点空间利用率,还是时间范围的影响更大,一般还是推荐使用DATETIME。
四、字符串类型
官网详解:https://dev.mysql.com/doc/refman/5.7/en/char.html
注意:CHAR 和 VARCHAR 是最常用的两种字符串类型。
1、char类型
定长,简单粗暴,浪费空间,存取速度快。
字符长度范围:0-255(一个中文是一个字符,是utf8编码的三个字节)
存储:
存储char类型的值时,会往右填充空格来满足长度
例如:指定长度为10,存>10个字符则报错,存<10个字符则用空格填充直到凑够10个字符存储
检索:
在检索或查询时,查出的结果会自动删除尾部的空格,除非我们打开pad_char_to_full_length SQL模式 (SET sql_mode = 'PAD_CHAR_TO_FULL_LENGTH';)
2、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让其现出原形。
mysql> create table t13(name char(5)); Query OK, 0 rows affected (0.02 sec) mysql> create table t14(name varchar(5)); Query OK, 0 rows affected (0.02 sec) mysql> insert into t13 value('李杰 '); Query OK, 1 row affected (0.00 sec) mysql> insert into t14 values('李杰 '); Query OK, 1 row affected (0.01 sec) # 在检索时char很不要脸地将自己浪费的2个字符给删掉了,装得好像自己没浪费过空间一样,而varchar很老实,存了多少就显示多少 mysql> select char_length(name) from t13; # char存的是五个字符,但查询只显示了2个 +-------------------+ | char_length(name) | +-------------------+ | 2 | +-------------------+ 1 row in set (0.01 sec) mysql> select char_length(name) from t14; # varchar是有几个存几个,因此应该是3个 +-------------------+ | char_length(name) | +-------------------+ | 3 | +-------------------+ 1 row in set (0.01 sec) # 执行下面的命令,修改模式,让char现出原形 mysql> SET sql_mode = 'PAD_CHAR_TO_FULL_LENGTH'; Query OK, 0 rows affected, 1 warning (0.00 sec) # 再次检查,就会显示char存的是五个字符 mysql> select char_length(name) from t13; +-------------------+ | char_length(name) | +-------------------+ | 5 | +-------------------+ 1 row in set (0.00 sec) mysql> select char_length(name) from t14; +-------------------+ | char_length(name) | +-------------------+ | 3 | +-------------------+ 1 row in set (0.00 sec) # mysql在比较时,不管末尾的空格 mysql> select name from t13 where name='李杰'; # 比较不管末尾空格 +-----------+ | name | +-----------+ | 李杰 | +-----------+ 1 row in set (0.00 sec) mysql> select name from t13 where name=' 李杰'; # 只会去掉末尾的空格 Empty set (0.00 sec) # char类型:2个中文字符+3个空格=2*3+3=9 Bytes mysql> select name, length(name) from t13; +-----------+--------------+ | name | length(name) | +-----------+--------------+ | 李杰 | 9 | +-----------+--------------+ 1 row in set (0.00 sec) # varchar类型:2个中文类型+1个空格=2*3+1=7 Bytes mysql> select name, length(name) from t14; +---------+--------------+ | name | length(name) | +---------+--------------+ | 李杰 | 7 | +---------+--------------+ 1 row in set (0.00 sec)
2、虽然char 和 varchar 的存储方式不太相同,但是对两个字符串的比较,都只比较其值,忽略CHAR值存在的右填充,即使将SQL_MODE设置为PAD_CHAR_TO_FULL_LENGTH 也一样,但这不适用于like
Values in CHAR and VARCHAR columns are sorted and compared according to the character set collation assigned to the column. All MySQL collations are of type PAD SPACE. This means that all CHAR, VARCHAR, and TEXT values are compared without regard to any trailing spaces. “Comparison” in this context does not include the LIKE pattern-matching operator, for which trailing spaces are significant. For example: mysql> CREATE TABLE names (myname CHAR(10)); Query OK, 0 rows affected (0.03 sec) mysql> INSERT INTO names VALUES ('Monty'); Query OK, 1 row affected (0.00 sec) mysql> SELECT myname = 'Monty', myname = 'Monty ' FROM names; +------------------+--------------------+ | myname = 'Monty' | myname = 'Monty ' | +------------------+--------------------+ | 1 | 1 | +------------------+--------------------+ 1 row in set (0.00 sec) mysql> SELECT myname LIKE 'Monty', myname LIKE 'Monty ' FROM names; +---------------------+-----------------------+ | myname LIKE 'Monty' | myname LIKE 'Monty ' | +---------------------+-----------------------+ | 1 | 0 | +---------------------+-----------------------+ 1 row in set (0.00 sec) # like查询的时候,就不会去掉末尾的空格了,必须保证是完整的 mysql> select name from t13 where name like '李杰 '; Empty set (0.00 sec) mysql> select name from t13 where name like '李杰 '; Empty set (0.00 sec) mysql> select name from t13 where name like '李杰 '; +-----------+ | name | +-----------+ | 李杰 | +-----------+ 1 row in set (0.00 sec)
3、总结
(1)常用字符串系列:char与varchar对比
char类型的优点是简单,存取速度都比较快,但是浪费空间。
varchar类型优点是更加节约空间,存取速度都比较慢,存需要先存头再存数据,取需要先读头再取数据。
因为现在设备的存储空间已经不再那么紧缺,系统更在意数据的存取速度,因此大部分情况都是使用char类型。
平时使用中,尽量把定长的数据往前放,把变长的数据往后放。尽量不要在一张表中char和varchar混用。
(2)其他字符串系列(效率: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 char(16), -> sex enum('male', 'female', 'other'), # 在范围内多选一 -> level enum('vip1', 'vip2', 'vip3'), -> hobbies set('play', 'music', 'read', 'run') # 在范围内多选多 -> ); Query OK, 0 rows affected (0.02 sec) mysql> insert into consumer values -> (1,'egon','male','vip2','music'); Query OK, 1 row affected (0.00 sec) mysql> select * from consumer; +------+------------------+------+-------+---------+ | id | name | sex | level | hobbies | +------+------------------+------+-------+---------+ | 1 | egon | male | vip2 | music | +------+------------------+------+-------+---------+ 1 row in set (0.00 sec) mysql> insert into consumer values (2,'alex','xxx','vip2','music'); # 乱填的内容不会正常显示 Query OK, 1 row affected, 1 warning (0.00 sec) mysql> select * from consumer; +------+------------------+------+-------+---------+ | id | name | sex | level | hobbies | +------+------------------+------+-------+---------+ | 1 | egon | male | vip2 | music | | 2 | alex | | vip2 | music | +------+------------------+------+-------+---------+ 2 rows in set (0.00 sec) mysql> insert into consumer values (3,'zuli','female','vip3','music,play'); Query OK, 1 row affected (0.01 sec) mysql> select * from consumer; +------+------------------+--------+-------+------------+ | id | name | sex | level | hobbies | +------+------------------+--------+-------+------------+ | 1 | egon | male | vip2 | music | | 2 | alex | | vip2 | music | | 3 | zuli | female | vip3 | play,music | +------+------------------+--------+-------+------------+ 3 rows in set (0.00 sec)