MySQL学习之路5

数据类型和运算符

1 . MySQL数据类型介绍
MySQL主要支持的数据类型有:数值类型、日期/时间类型、字符串类型。
(1)数值数据类型:包括整数类型TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT、浮点小数数据类型FLOAT和DOUBLE、定点小数类型DECIMAL。
(2)日期/时间类型:包括YEAR、TIME、DATE、DATETIME和TIMESTAMP。
(3)字符串类型:包括CHAR、VARCHAR、BINARY、VARBINARY、BLOB、TEXT、ENUM和SET等。

1.1 整数类型
整数类型的属性字段可以添加AUTO_INCREMENT自增约束条件。
MySQL中的整数型数据类型:

类型名称 说明 存储需求
TINYINT 很小的整数 1个字节(8 bits)
SMALLINT 小的整数 2个字节
MEDIUMINT 中等大小的整数 3个字节
INT(INTEGER)INT 普通大小的整数 4个字节
BIGINT 大整数 8个字节
TINYINT需要1个字节(8 bits)来存储,那么TINYINT无符号数的最大值为2^8 - 1,即255; TINYINT无符号数的最大值为2^7 - 1,即127;

不同整数类型的取值范围

数据类型 有符号 无符号
TINYINT -128~127 0~255
SMALLINT -32768~32767 0~65535
MEDIUMINT -8388608~8388607 0~16777215
INT(INTEGER)INT -2147483648~2147482617 0~4294967295
BIGINT -9223372036854775808~9223372036854775807 0~18446744073709551615

下面你需要注意的地方是:如INT(11)里的111表示的是该数据类型指定的显示宽度。显示宽度和数据类型的取值范围是无关的 。显示宽度只是指明MySQL最大可能显示的数字个数,数值的位数小于指定的宽度时会由空格填充;如果插入大于显示宽度的值,只要该值不超过该类型整数的取值范围,数值一样可以插入并能够显示出来。

例:创建表rmp1,其中字段x、y、z、m、n数据类型依次为TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT,SQL语句如下:

mysql> CREATE TABLE rmp1(x TINYINT, y SMALLINT, z MEDIUMINT, m INT, n BIGINT);
Query OK, 0 rows affected (2.13 sec)

查看表结构:

mysql> DESC rmp1;
+-------+--------------+------+-----+---------+-------+
| Field | Type         | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| x     | tinyint(4)   | YES  |     | NULL    |       |
| y     | smallint(6)  | YES  |     | NULL    |       |
| z     | mediumint(9) | YES  |     | NULL    |       |
| m     | int(11)      | YES  |     | NULL    |       |
| n     | bigint(20)   | YES  |     | NULL    |       |
+-------+--------------+------+-----+---------+-------+
5 rows in set (0.19 sec)

可以看到系统给每一个字段添加不同的默认使用宽度。
注:显示宽度只用于显示,并不能限制取值范围和占用空间,如:INT(3)会占用4个字节的存储空间,但是允许的最大值是INT允许的最大值。

1.2浮点数类型和定点数类型
浮点类型有两种:单精度浮点数类型(FLOAT)和双精度浮点类型(DOUBLE)。
定点类型:DECIMAL。
这两种类型均可以使用(M,N)表示,M(精度)表示总共的位数;N(标度)表示小数的位数。
MySQL中的小数类型

类型名称 说明 存储需求
FLOAT 单精度浮点数 4个字节
DOUBLE 双精度浮点数 8个字节
DECIMAL (M,D) DEC 压缩的“严格”定点数 M+2个字节
不同类型的取值范围:
数据类型 有符号 无符号
FLOAT -3.402823466E+38~-1.175494351E-38 0和1.175494351E-38~3.402823466E+38
DOUBLE -1.7976931348623157E+308~-2.2250738585072014E-308 0和2.2250738585072014E-308~1.7976931348623157E+308

提示:如果用户指定的精度超出精度范围,则会四舍五入进行处理。

例:创建表tmp2,其中字段x、y、z数据类型依次为FLOAT(5,1)、DOUBLE(5,1)和DECIMAL(5,1),向表中插入数据5.12,5.15和5.123,SQL语句如下:

mysql> CREATE TABLE tmp2(x FLOAT(5,1), y DOUBLE(5,1), z DECIMAL(5,1));
Query OK, 0 rows affected (0.62 sec)

mysql> INSERT INTO tmp2 VALUES(5.12,5.15,5.123);
Query OK, 1 row affected, 1 warning (0.22 sec)

mysql> SHOW WARNINGS;
+-------+------+----------------------------------------+
| Level | Code | Message                                |
+-------+------+----------------------------------------+
| Note  | 1265 | Data truncated for column 'z' at row 1 |
+-------+------+----------------------------------------+
1 row in set (0.14 sec)

可以看到FLOAT和DOUBLE在进行四舍五入时没有给出警告,但给出了z字段数值被截断警告。
查看结果:

mysql> SELECT * FROM tmp2;
+------+------+------+
| x    | y    | z    |
+------+------+------+
|  5.1 |  5.2 |  5.1 |
+------+------+------+
1 row in set (0.18 sec)

FLOAT和DOUBLE在不指定精度时,默认会按照实际的精度,而DECIMAL在不指定精度时会默认(10,0)。
注:浮点数能表示更大的数据范围,但会引起精度问题。

1.3日期与时间类型
MySQL中表示日期的数据类型:DATETIME、DATETIME、STAMP、TIME和YEAR。

类型名称 日期格式 日期范围 存储需求
YEAR YYYY 1901~2155 1字节
TIME HH:MM:SS -838:59:59~838:59:59 3字节
DATE YYYY-MM-DD 1000-01-01~9999-12-31 3字节
DATETIME YYYY-MM-DD HH-MM-SS 1000-01-01 00:00:00~9999-12-31 23:59:59 8字节
TIMESTAMP YYYY-MM-DD HH:MM:SS 1970-01-01 00:00:01 UTC ~ 2038-01-19 03:14:07 UTC 4字节

1.year
可以使用下列格式指定YEAR的值:

  • 以4位字符串或数字表示,即’YYYY’或者YYYY,范围:‘1901’~‘2155’.
  • 以2位字符串格式表示, ‘00’ ~ ‘69’ 和 ‘70’ ~ '99’范围的值分别被转换为2000~ 2069和1970~ 1999范围的YEAR值。'0’与’00’的作用相同,若插入超过取值范围的值将被转换为2000。
  • 以2位数字表示与以字符串格式表示类似。注意:这里0值会被转换成0000.

例:创建表tmp3,定义数据类型为YEAR的字段y,向表中插入值为2010,‘2010’,‘2166’,SQL语句如下:

mysql> CREATE TABLE tmp3(y YEAR);
Query OK, 0 rows affected (1.78 sec)

mysql> INSERT INTO tmp3 values(2010),('2010'),('2166');
ERROR 1264 (22003): Out of range value for column 'y' at row 3

出现错误,超出范围。(这里与上面笔记所说不相符,大概是MySQL版本的问题)

例:向tmp3表中y字段插入2位字符串表示的YEAR值,分别为‘0’、‘00’、‘77’和‘10’,语句如下:

首先删除表中数据
mysql> DELETE FROM tmp3;
Query OK, 0 rows affected (0.14 sec)

向表中插入数据
mysql> INSERT INTO tmp3 values('0'),('00'),('77'),('10');
Query OK, 4 rows affected (0.10 sec)
Records: 4  Duplicates: 0  Warnings: 0

查看结果
mysql> SELECT * FROM tmp3;
+------+
| y    |
+------+
| 2000 |
| 2000 |
| 1977 |
| 2010 |
+------+
4 rows in set (0.02 sec)

其他就不一 一展示。

2.TIME
格式:

  • ‘D HH:MM:SS’/‘HH:MM:SS’/‘D HH:MM’/‘D HH’/‘SS’。这里D表示日(0~34),在插入数据库时,D被转换为小时保存,格式为“D*24+HH”。
  • ‘HHMMSS’。

例:创建数据表tmp4,定义数据类型为TIME字段t,向表中插入值’10:05:05’,‘23:23’,‘2 10:10’,‘3 02’,‘10’,SQL语句如下:

mysql> CREATE TABLE tmp4(t TIME);
Query OK, 0 rows affected (0.56 sec)

mysql> INSERT INTO tmp4 VALUES('10:05:05'),('23:23'),('2 10:10'),('3 02'),('10');
Query OK, 5 rows affected (0.14 sec)
Records: 5  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM tmp4;
+----------+
| t        |
+----------+
| 10:05:05 |
| 23:23:00 |
| 58:10:00 |
| 74:00:00 |
| 00:00:10 |
+----------+
5 rows in set (0.12 sec)

注:在使用D HH格式时,小时一定要使用双位数。

例:向表tmp4中插入值’101112’,111213,‘0’,107010,SQL语句如下:
首先删除数据:

mysql> DELETE FROM tmp4;
Query OK, 5 rows affected (0.18 sec)

向表中插入数据:

mysql> INSERT INTO tmp4 VALUES('10112'),(111213),('0'),(107010);
ERROR 1292 (22007): Incorrect time value: '107010' for column 't' at row 4

可以看到有错误产生,即在插入第4条数据时,数据超出了范围,原因是70超出了60分钟。

下面使用系统日期函数向TIME字段插入值。
例:向tmp4插入系统当前时间,SQL语句如下:

mysql> INSERT INTO tmp4 VALUES(CURRENT_TIME),(NOW());
Query OK, 2 rows affected (0.18 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM tmp4;
+----------+
| t        |
+----------+
| 08:43:00 |
| 08:43:00 |
+----------+
2 rows in set (0.00 sec)

1.3DATE类型(3bytes)

  1. ‘YYYY-MM-DD’ or 'YYYYMMDD’字符格式表示日期,取值范围:
    ‘1000-0101’~ ‘9999-12-3’ 。

  2. ‘YY-MM-DD’~ 'YYMMDD’字符格式表示日期
    '00~ 69’表示‘2000 ~ 2069’
    '70~99’表示‘1970 ~1999’。

  3. YY-MM-DD or YYMMDD数字格式表示日期,范围与2相似,但是YY-MM-DD需要用双引号引上。

例:创建数据表tmp5,定义数据类型为DATE的字段d,向表中插入“YYYY-MM-DD”和“YYYYMMDD”字符串格式日期,SQL语句如下:

mysql> CREATE TABLE tmp5(d DATE);
Query OK, 0 rows affected (0.53 sec)

mysql> INSERT INTO tmp5 VALUES('1998-08-08'),('19980808'),('20101010');
Query OK, 3 rows affected (0.06 sec)

查看结果:

mysql> SELECT * FROM tmp5;
+------------+
| d          |
+------------+
| 1998-08-08 |
| 1998-08-08 |
| 2010-10-10 |
+------------+
3 rows in set (0.00 sec)

例:向tmp5表中插入“YY-MM-DD”和“YYMMDD”字符串格式日期,SQL 语句如下:

mysql> DELETE FROM tmp5;
Query OK, 3 rows affected (0.06 sec)

mysql> INSERT INTO tmp5 VALUES('99-09-09'),('990909'),('000101'),('111111');
Query OK, 4 rows affected (0.11 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM tmp5;
+------------+
| d          |
+------------+
| 1999-09-09 |
| 1999-09-09 |
| 2000-01-01 |
| 2011-11-11 |
+------------+
4 rows in set (0.00 sec)

例:向tmp5表中插入YY-MM-DD和YYMMDD数字格式日期,SQL语句如下:

mysql> INSERT INTO tmp5 VALUES("990909"),(990909),(000101),(111111);
Query OK, 4 rows affected (0.11 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM tmp5;
+------------+
| d          |
+------------+
| 1999-09-09 |
| 1999-09-09 |
| 2000-01-01 |
| 2011-11-11 |
+------------+
4 rows in set (0.00 sec)

例:向tmp5插入系统当前日期:

mysql> DELETE FROM tmp5;
Query OK, 4 rows affected (0.08 sec)

mysql> INSERT INTO tmp5 VALUES(CURRENT_DATE()),(NOW());
Query OK, 2 rows affected, 1 warning (0.06 sec)
Records: 2  Duplicates: 0  Warnings: 1

mysql> SELECT * FROM tmp5;
+------------+
| d          |
+------------+
| 2018-11-30 |
| 2018-11-30 |
+------------+
2 rows in set (0.00 sec)

      CURRENT_DATE()只返回当前日期值
      NOW()返回日期和时间值,这里d为DATE类型,故只保存了DATE部分               

提示:MySQL允许不严格的语法:任何标点符号都可以用作日期部分之间的间隔符。

1.4DATETIME
格式:

  1. ‘YYYY-MM-DD HH:MM:SS’、‘YYYYMMDDHHMMSS’字符串格式表示,取值范围‘1000-01-01 00:00:00’~‘9999-12-3 23:59:59’。
  2. ‘YY-MM-DD HH:MM:SS’、‘YYMMDDHHMMSS’字符串格式表示,取值范围YY表示年值,其取值范围与前面日期的相同。
  3. YYYYMMDDHHMMSS、YYMMDDHHMMSS数字格式表示。

例:创建数据表tmp6,定义数据类型为DATETIME的字段dt,向表中插入日期和时间值(这里只演示数字格式和插入系统当前日期和时间值)
创建数据表:

mysql> CREATE TABLE tmp6(dt DATETIME);
Query OK, 0 rows affected (0.46 sec)

插入值:

mysql> INSERT INTO tmp6 VALUES(19970823121314),(NOW());
Query OK, 2 rows affected (0.13 sec)
Records: 2  Duplicates: 0  Warnings: 0

查看值:

mysql> SELECT * FROM tmp6;
+---------------------+
| dt                  |
+---------------------+
| 1997-08-23 12:13:14 |
| 2018-11-30 14:36:34 |
+---------------------+
2 rows in set (0.07 sec)

MySQL允许不严格的语法,实验:
1

mysql> INSERT INTO tmp6 VALUES('2018$06&18 08\18+50');
ERROR 1292 (22007): Incorrect datetime value: '2018$06&18 0818+50' for column 'dt' at row 1

2

mysql> INSERT INTO tmp6 VALUES('2018$06&18 08/18?50');
Query OK, 1 row affected (0.14 sec)

3

mysql> INSERT INTO tmp6 VALUES('2018$06&18 08\18\15');
ERROR 1292 (22007): Incorrect datetime value: '2018$06&18 081815' for column 'dt' at row 

只有第2个可以插入。

5.TIMESTAMP
TIMESTAMP显示格式与DATETIME相同,日期格式为:YYYY-MM-DD HH:MM:SS。但取值范围比DATETIME小,其取值范围为:‘1970-01-01 00:00:01’ UTC ~ ‘2038-01-19 03:14:07’ UTC,UTC:世界标准时间。

例:创建数据表tmp7,向表中插入值:

mysql> CREATE TABLE tmp7(ts TIMESTAMP);
Query OK, 0 rows affected (0.38 sec)
mysql> INSERT INTO tmp7 VALUES('97@12@12 12@12@12'),(NOW());
Query OK, 2 rows affected (0.15 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM tmp7;
+---------------------+
| ts                  |
+---------------------+
| 1997-12-12 12:12:12 |
| 2018-11-30 14:52:11 |
+---------------------+
2 rows in set (0.00 sec)

TIMESTAMP存储的时间与当前所处的时区有关。

例:向tmp7表中插入当前日期,查看插入值,将时区改为东10区,再次查看插入值:

mysql> DELETE FROM tmp7;
Query OK, 2 rows affected (0.13 sec)

mysql> INSERT INTO tmp7 VALUES(NOW());
Query OK, 1 row affected (0.06 sec)

mysql> SELECT * FROM tmp7;
+---------------------+
| ts                  |
+---------------------+
| 2018-11-30 14:55:07 |
+---------------------+
1 row in set (0.00 sec)

mysql> set time_zone='+10:00';
Query OK, 0 rows affected (0.06 sec)

mysql> SELECT * FROM tmp7;
+---------------------+
| ts                  |
+---------------------+
| 2018-11-30 16:55:07 |
+---------------------+
1 row in set (0.00 sec)

1.5字符串类型
MySQL中的字符串类型:

类型名称 说明 存储需求
CHAR(M) 固定长度非二进制字符串 M字节,1<=M<=255
VARCHAR(M) 变长非二进制字符串 L+1字节,L<=M,1<=M<=255
TINYTEXT 非常小的非二进制字符串 L+1字节,L<2^8
TEXT 小的非二进制字符串 L+2字节,L<2^16
MEDIUMTEXT 中等大小的非二进制字符串 L+3字节,L<2^24
LONGTEXT 大的非二进制字符串 L+4字节,L<2^32
ENUM 枚举类型,只能有一个枚举字符串值 1或2个字节,取决于枚举值的数目(最大值65535)
SET 一个设置,字符串对象可以有0个或多个SET成员 1,2,3,4或8个字节,取决于集合成员的数量(最多64个成员)

1.CHAR与VARCHAR
CHAR固定长度,当检索到CHAR值时,尾部的空格将被删除掉,且无论存入的长度为多少,所占的空间均为定义时指定的字符串列长。

VARCHAR在值保存和检索时尾部的空格仍保留,且其定义的列所占的字节数为实际长度加1。

例:创建tmp8表,定义字段ch(CHAR(4)),vch(VARCHAR(4))向表中插入数据“ab ”,SQL语句如下:

mysql> CREATE TABLE tmp8(
    -> ch CHAR(4),
    -> vch VARCHAR(4)
    -> );
Query OK, 0 rows affected (1.51 sec)

mysql> INSERT INTO tmp8 VALUES('ab  ','ab  ')
    -> ;
Query OK, 1 row affected (0.16 sec)

查询结果:

mysql> SELECT concat('(',ch,')'),concat('(',vch,')') FROM tmp8;
+--------------------+---------------------+
| concat('(',ch,')') | concat('(',vch,')') |
+--------------------+---------------------+
| (ab)               | (ab  )              |
+--------------------+---------------------+
1 row in set (0.21 sec)

可以看到,ch在保存值时把尾部空格删去,而vch仍保留尾部空格。

2.TEXT类型
TEXT列保存非二进制字符串,如文章内容、评论等。
Text类型有四种:TINYTEXT、TEXT、MEDIUMTEXT、LONGTEXT。

3.ENUM类型
ENUM是一个字符串对象,其值为表创建时在列规定中枚举的一列值。
语法格式:字段名 ENUM('值 1' , '值 2' , ... , '值 n')
每个枚举值均有一个索引值,但是请注意存储值不是一个十分明智的选择,故一般存储索引。
ENUM类型的取值范围:

索引
NULL NULL
‘’ 0
first 1
second 2
third 3

例:创建表tmp9,定义ENUM类型的列enm(‘first’ , ‘second’ , ‘third’),查看列成员的索引值:

mysql> CREATE TABLE tmp9(enm ENUM('first','second','third'));
Query OK, 0 rows affected (0.54 sec)

mysql> INSERT INTO tmp9 values('first'),('second'),('third'),(NULL);
Query OK, 4 rows affected (0.15 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> SELECT enm ,enm+0 FROM tmp9;
+--------+-------+
| enm    | enm+0 |
+--------+-------+
| first  |     1 |
| second |     2 |
| third  |     3 |
| NULL   |  NULL |
+--------+-------+
4 rows in set (0.54 sec)

我试了一下,发现我mysql版本无法输入‘’,我想应该是需要更高的版本吧!

4.set类型
例:创建表tmp11,定义set类型字段,取值列表为(‘a’,‘b’,‘c’,‘d’),插入数据(‘a’),(‘a,b,a’),(‘c,a,d’),(‘a,x,b,y’),SQL语句如下:

mysql> CREATE TABLE tmp11(s SET('a','b','c','d'));
Query OK, 0 rows affected (0.37 sec)

mysql> INSERT INTO tmp11 VALUES('a'),('a,b,a'),('c,a,b'),('a,x,b,y');
ERROR 1265 (01000): Data truncated for column 's' at row 4

可以看到由于插入了SET列不支持的类型,出现错误。
重新插入

mysql> INSERT INTO tmp11 VALUES('a'),('a,b,a'),('c,a,b');
Query OK, 3 rows affected (0.04 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM tmp11;
+-------+
| s     |
+-------+
| a     |
| a,b   |
| a,b,c |
+-------+
3 rows in set (0.00 sec)

从结果可以看出,set不允许重复,且有先后顺序明确。

1.5 二进制类型
MySQL支持两类字符型数据:文本字符串、二进制字符串。
二进制数据类型有:BIT、BINARY、VARBINARY、TINYBLOB、BLOB、MEDIUMBOLB、LONGBLOB。

1.BIT类型
BIT数据类型用来保存位字段值,BIT(M),M表示每个值的位数,范围1~64。若M被忽略,默认1。
例:创建表tmp12,定义BIT(4)类型的字段b,向表中插入数据2、9、15、16。

mysql> INSERT INTO tmp12 VALUES(2),(9),(15),(16);
ERROR 1406 (22001): Data too long for column 'b' at row 4

出现错误,16超出了4位二进制数的范围。

mysql> SELECT BIN(b+0) FROM tmp12;
+----------+
| BIN(b+0) |
+----------+
| 10       |
| 1001     |
| 1111     |
+----------+
3 rows in set (0.09 sec)

mysql> SELECT b+0 FROM tmp12;
+------+
| b+0  |
+------+
|    2 |
|    9 |
|   15 |
+------+
3 rows in set (0.00 sec)

其中: b+0表示将二进制的结果转换为对应的数字值,BIN()函数将数字转化为二进制。

2.BINARY和VARBINARY
BINARY和VARBINARY类似于CHAER和VARCHAR,BINARY类型的长度是固定的,VARBINARY类型的长度是可变的且实际占用空间为字符串实际长度加一。
例:创建表tmp13,定义BINARY(3)类型字段b和VARBINARY(3)类型的字段vb,并向表中插入数据‘5’,比较两个字段的存储空间:

mysql> CREATE TABLE tmp13(b BINARY(3),vb VARBINARY(3));
Query OK, 0 rows affected (0.34 sec)

mysql> INSERT INTO tmp13 VALUES(5,5);
Query OK, 1 row affected (0.02 sec)

mysql> SELECT length(b),length(vb) FROM tmp13;
+-----------+------------+
| length(b) | length(vb) |
+-----------+------------+
|         3 |          1 |
+-----------+------------+
1 row in set (0.00 sec)

进一步确认5在两个字段中不同的存储方式:

mysql> SELECT b,vb,b='5',b='5\0\0',vb='5',vb='5\0\0' FROM tmp13;
+------+------+-------+-----------+--------+------------+
| b    | vb   | b='5' | b='5\0\0' | vb='5' | vb='5\0\0' |
+------+------+-------+-----------+--------+------------+
| 5    | 5     |       0 |            1 |         1 |               0 |
+------+------+-------+-----------+--------+------------+
1 row in set (0.00 sec)

b字段不足的空间填充了‘\0’。

3.BOLB类型
BLOB类型的存储范围:

数据类型 存储范围
TINYBLOB 最大长度为255(28-1)字节
BLOB 最大长度为65535(216-1)字节
MEDIUMBLOB 最大长度为16777215(224-1)字节
LONGBLOB 最大长度为4294967295或4GB(232-1)字节

BLOB列存储的是二进制字符串(字节字符串);TEXT列存储的是字符字符串。BLOB列没有字符集,并且排序和比较基于列字节的数值;TEXT列有一个字符集,并且根据字符集对值进行排序和比较。

猜你喜欢

转载自blog.csdn.net/weixin_43037507/article/details/82980508