Skip to content

数据类型和运算符

MySQL 支持多种数据类型,主要有数值类型、日期/时间类型和字符串类型

(1) 数值类型: 包括整数类型 TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT、浮点小数数据类型 FLOAT 和 DOUBLE,定点小数类型 DECIMAL。
(2) 日期/时间类型: 包括 YEAR、TIME、DATE、DATETIME 和 TIMESTAMP
(3) 字符串类型: 包括 CHAR、VARCHAR、BINARY、VARBINARY、BLO、TEXT、ENUM 和 SET 等。字符串类型又分为文本字符串和二进制字符串

整数类型

数值型数据类型主要用来存储数字,MySQL 提供了多种数值数据类型,不同的数据类型提供不同的取值范围,可以存储的值范围越大,其所需要的存储空间也会越大。
MySQL 主要提供的整数类型有 TINYINT、SMLLINT、MEDIUMINT、INT(INTEGER)、BIGINT。
整数类型的属性字段可以添加 AUTO_INCREMENT 自增约束条件。

类型名称 说明 存储需求
TINYINT 很小的整数 1字节
SMALLINT 小的整数 2字节
MEDIUMINT 中等大小的整数 3字节
INT(INTEGER) 普通大小的整数 4字节
BIGINT 大整数 8字节

从表中可以看到,不同类型整数存储所需的字节数是不同的,占用最小的是 TINYINT 类型,占用字节最大的是 BIGINT 类型,相应的占用字节越多的类型所能表示的数值范围越大。
根据占用字节数可以求出每一种数据类型的取值范围。

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

例如有如下创建表的语句:

1
2
3
4
5
6
7
CREATE TABLE tb_emp1
(
    id  INT(11),
    name  VARCHAR(25),
    deptId  INT(11),
    salary  FLOAT
);

id 字段的数据类型为 INT(11),注意后面的数字 11,它表示的是该数据类型指定的显示宽度,即能够显示的数值中数字的个数。
例如,假设声明一个 INT 类型的字段:

1
year INT(4)

该声明指明,在 year 字段中的数据一般只显示 4 位数字的宽度

注意:
显示宽度和数据类型的取值范围是无关的。
显示宽度只是指明 MySQL 最大可能显示的数字个数,数值的位数小于指定的宽度时会由空格填充;
如果插入了大于显示宽度的值,只要该值不超过该类型整数的取值范围,数值依然可以插入,而且能够显示出来。
例如,向 year 字段插入一个数值 19999,当使用 SELECT 查询该列值的时候,MySQL 显示的将是完整的带有 5 位数字的 19999,而不是 4 位数字的值。

其他整型数据类型也可以在定义表结构时指定所需要的显示宽度,如果不指定,则系统为每一种类型指定默认的宽度值

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

1
2
3
4
5
6
7
8
CREATE TABLE tmp1
(
    x  TINYINT,
    y SMALLINT,
    z  MEDIUMINT,
    m  INT,
    n  BIGINT
);

例如,TINYINT 有符号数和无符号数的取值范围分别是 -128-127 和 0-255,由于负号占了一个数字位,因此 TINYINT 默认的显示宽度为 4.
同理,其他整数类型的默认显示宽度预期有符号数的最小值的宽度相同。

浮点数类型和定点类型

MySQL 中使用浮点数和定点数来表示小数。
浮点数类型有两种: 单精度浮点类型(FLOAT)和双精度浮点类型(DOUBLE)。
定点数类型只有一种: DECIMAL。浮点数类型和定点数类型都可以用 (M,N)来表示。
其中,M 称为精度,表示总共的位数;N 称为标度,表示小数的位数。

类型名称 说明 存储需求
FLOAT 单精度浮点数 4字节
DOUBLE 双精度浮点数 8字节
DECIMAL(M,D), DEC 压缩的“严格”定点数 M+2字节

DECIMAL 类型不同于 FLOAT 和 DOUBLE,DECIMAL 实际是以串存放的,可能的最大取值范围与 DOUBLE 一样,但是其有效的取值范围由 M 和 D 的值决定。
如果改变 M 而固定 D,则其取值范围将随 M 的变大而变大。

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 语句如下:

1
2
3
4
5
6
CREATE TABLE tmp2
(
    x  FLOAT(5,1),
    y  DOUBLE(5,1),
    z  DECIMAL(5,1)
);

向表中插入数据:

1
INSERT INTO tmp2 VALUES(5.12,5.15,5.123);
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
mysql> INSERT INTO tmp2 VALUES(5.12,5.15,5.123);
Query OK, 1 row affected, 1 warning (0.01 sec)

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

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

1
2
3
4
5
6
7
mysql> SELECT * FROM tmp2;
+------+------+------+
| x    | y    | z    |
+------+------+------+
|  5.1 |  5.2 |  5.1 |
+------+------+------+
1 row in set (0.00 sec)

FLOAT 和 DOUBLE 在不指定精度时,默认会按照实际的精度(由计算机硬件和操作系统决定),DECIMAL 若不指定精度则默认是 (10,0)

浮点数相对定点数的优点是在长度一定的情况下,浮点数能够表示更大的数据范围; 它的缺点是会引起精度问题。

提示:
在 MySQL 中,定点数以字符串形式存储,在对精度要求比较高的时候(如货币、科学数据等)使用 DECIMAL 的类型比较好,另外两个浮点数进行减法和比较运算时容易出问题,所以在使用浮点数时需要注意,并尽量避免做浮点数比较

日期与时间类型

MySQL 中有多种表示日期的数据类型,主要有 DATETIME、DATE、TIMESTAMP、TIME 和 YEAR。
例如,当只记录年信息的时候,可以只使用 YEAR 类型,而没有必要使用 DATE.
每一个类型都有合法的取值范围,当指定确定不合法的值时将“零”值插入到数据库中

类型名称 日期格式 日期范围 存储需求
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-3 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字节

YEAR

YEAR 类型是一个单字节类型,用于表示年,在存储时只需要 1 字节。可以使用各种格式指定 YEAR 值,如下所示:

以 4 位字符串或者 4 位数字格式表示 YEAR,范围为 '1901' - '2155'。输入格式为 'YYYY' 或者 YYYY。
例如,输入 '2010' 或 2010,插入到数据库的值均为 2010

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

1
2
3
4
CREATE TABLE tmp3
(
    y  YEAR
);
1
INSERT INTO tmp3 values(2010),('2010');

再次向表中插入数据:

1
INSERT INTO tmp3 values('2166');
1
2
mysql> INSERT INTO tmp3 values('2166');
ERROR 1264 (22003): Out of range value for column 'y' at row 1
1
2
3
4
5
6
7
8
mysql> SELECT * FROM tmp3;
+------+
| y    |
+------+
| 2010 |
| 2010 |
+------+
2 rows in set (0.00 sec)

TIME

TIME 类型用在只需要时间信息的值,在存储时需要 3 字节,格式为 'HH:MM:SS'。
其中,HH 表示小时,MM 表示分钟,SS 表示秒。
TIME 类型的取值范围为 -838:59:59 - 838:59:59,小时部分会如此大的原因是 TIME 类型不仅可以用于表示一天的时间(必须小于 24 小时),还可能是某个事件过去的时间或两个事件之间的时间间隔(可以大于 24 小时,或者甚至为负)。可以使用各种格式指定 TIME 值。

(1) 'D HH:MM:SS' 格式的字符串。可以使用下面任何一种“非严格”的语法: 'HH:MM:SS'、'HH:MM'、'D HH:MM'、'D HH' 或 'SS'。
这里的 D 比啊是日,可以取 0-34 之间的值。在插入数据库时,D 被转换为小时保存,格式为 "D * 24 + HH"

(2) 'HHMMSS' 格式的、没有间隔符的字符串或者 HHMMSS 格式的数值,假定是有意义的时间。例如: '101112' 被理解为 '10:11:12',但 '109712' 是不合法的(它有一个没有意义的分钟部分),存储时将变成 00:00:00

提示:
为 TIME 列分配简写值时应注意: 如果没有冒号,MySQL 解释值时,假定最右边的两位表示秒。(MySQL 解释 TIME 值为过去的时间而不是当天的时间。)
例如,你可能认为 '1112' 和 1112 表示 11:12:00(11 点 12 分),但 MySQL 将它们解释为 00:11:12(11 分 12 秒)。
同样 '12' 和 12 被解释为 00:00:12.
相反,TIME 值中如果使用冒号则肯定被看作当天的时间。
也就是说,'11:12' 表示 11:12:00,而不是 00:11:12

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

1
2
3
4
CREATE TABLE tmp4
(
    t TIME
);
1
INSERT INTO tmp4 values('10:05:05'),('23:23'),('2 10:10'),('302'),('10');
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
mysql> INSERT INTO tmp4 values('10:05:05'),('23:23'),('2 10:10'),('302'),('10');
Query OK, 5 rows affected (0.00 sec)
Records: 5  Duplicates: 0  Warnings: 0

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

提示:
在使用 'D HH' 格式时,小时一定要使用双位数值,如果是小于 10 的小时数,应在前面加 0

例: 向表 tmp4 中插入值 '101112'、111213、'0'、107010,SQL 语句如下:

删除表中数据:

1
DELETE FROM tmp4;

插入数据:

1
INSERT INTO tmp4 values('101112'),(111213),('0');

再向表中插入数据:

1
INSERT INTO tmp4 values(107010);
1
2
mysql> INSERT INTO tmp4 values(107010);
ERROR 1292 (22007): Incorrect time value: '107010' for column 't' at row 1

也可以使用系统日期函数向 TIME 字段列插入值。

例: 向 tmp4 表中插入系统当前时间:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
mysql> DELETE FROM tmp4;
Query OK, 3 rows affected (0.00 sec)

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

mysql> SELECT * FROM tmp4;
+----------+
| t        |
+----------+
| 14:04:13 |
| 14:04:13 |
+----------+
2 rows in set (0.00 sec)

DATE 类型

DATE 类型用在仅需要日期值时,没有时间部分,在存储时需要 3 字节。日期格式为 'YYYY-MM-DD'。
在给 DATE 类型的字段赋值时,可以使用字符串类型或者数字类型的数据插入,只要符合 DATE 的日期格式即可

文本字符串类型

字符串类型用来存储字符串数据,出了可以存储字符串数据之外,还可以存储其他数据,比如图片和声音的二进制数据。
MySQL 支持两类字符型数据: 文本字符串和二进制字符串。
文本字符串可以进行区分或者不区分大小写的串比较,还可以进行模式匹配查找。
在 MySQL 中,文本字符串类型是指 CHAR、VARCHAR、TEXT、ENUM 和 SET。

类型名称 说明 存储需求
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 一个设置,字符串对象可以有零个或多个 SET 成员 1、2、3、4 或 8 字节,取决于集合成员的数量(最多为 64 个成员)

VARCHAR 和 TEXT 类型都是变长类型,其存储需求取决于列值的实际长度(在前面的表格中用 L 表示),而不是取决于类型的最大可能尺寸。
例如,一个 VARCHAR(10) 列能保存最大长度为 10 个字符的字符串,实际的存储需要是字符串的长度 L 加上 1 字节(记录字符串的长度)。
对于字符串 "abcd",L 是 4 而存储要求是 5 字节。

CHAR 和 VARCHAR 类型

CHAR(M) 为固定长度字符串,在定义时指定字符串列长。
当保存时在右侧填充空格,以达到指定的长度。M 表示列长度,M 的范围是 0-255 个字符。
例如,CHAR(4) 定义了一个固定长度的字符串列,其包含的字符个数最大为 4。当检索到 CHAR 值时,尾部的空格将被删除。

VARCHAR(M) 是长度可变的字符串,M 表示最大列长度。M 的范围是 0-65535.
VARCHAR 的最大实际长度由最长的行的大小和使用的字符集确定,而其实际占用的空间为字符串的实际长度加 1.
例如,VARCHAR(50) 定义了一个最大长度为 50 的字符串,如果插入的字符串只有 10 个字符,则实际存储的字符串为 10 个字符和一个字符串结束字符。
VARCHAR 在值保存和检索时尾部的空格仍保留。

例: 下面将不同字符串保存到 CHAR(4) 和 VARCHAR(4) 列,说明 CHAR 和 VARCHAR 之间的差别:

插入值 CHAR(4) 存储需求 VARCHAR(4) 存储需求
'' ' ' 4字节 '' 1字节
'ab' 'ab ' 4字节 'ab' 3字节
'abc' 'abc ' 4字节 'abc' 4字节
'abcd' 'abcd' 4字节 'abcd' 5字节
'abcdef' 'abcd' 4字节 'abcd' 4字节

对比结果可以看到,CHAR(4) 定义了固定长度为 4 的列,不管存入的数据长度为多少,所占用的空间均为 4 个字节;
VARCHAR(4) 定义的列所占的字节数为实际长度加 1.

查询时,CHAR(4) 和 VARCHAR(4) 的值并不一定相同

例: 创建 tmp8 表,定义字段 ch 和 vch 数据类型一次为 CHAR(4)、VARCHAR(4),向表中插入数据 "ab ",SQL 语句如下:

1
2
3
4
CREATE TABLE tmp8 (
    ch CHAR(4),
    vch VARCHAR(4)
);
1
INSERT INTO tmp8 VALUES('ab  ','ab  ');
1
2
3
4
5
6
7
mysql> SELECT concat('(', ch, ')'), concat('(', vch, ')') FROM tmp8;
+----------------------+-----------------------+
| concat('(', ch, ')') | concat('(', vch, ')') |
+----------------------+-----------------------+
| (ab)                 | (ab  )                |
+----------------------+-----------------------+
1 row in set (0.00 sec)

从查询结果可以看到,ch 在保存 "ab " 时将末尾的两个空格删除了,而 vch 字段保留了末尾的两个空格。

TEXT 类型

TEXT 列保存非二进制字符串,如文章内容、评论等。当保存或查询 TEXT 列的值时,不删除尾部空格。
TEXT 类型分为 4 种: TINYTEXT、TEXT、MEDIUMTEXT 和 LONGTEXT。不同的 TEXT 类型的存储空间和长度不同。

(1) TINYTEXT 最大长度为 255(2^8 - 1)字符的 TEXT 列。
(2) TEXT 最大长度为 65535(2^{16} - 1) 字符的 TEXT 列
(3) MEDIUMTEXT 最大长度为 16777215(2^{24} - 1)字符的 TEXT 列
(4) LONGTEXT 最大长度为 4294967295(2^{32} - 1)或 4GB 字符的 TEXT 列

ENUM 类型

ENUM 是一个字符串对象,其值为表创建时在列规定中枚举的一列值。语法格式如下:

1
字段名 ENUM('值1','值2',...,'值n')

其中,"字段名" 指将要定义的字段,"值n" 指枚举列表中的第 n 个值。
ENUM 类型的字段在取值时,只能在指定的枚举列表中取,而且一次只能取一个
创建的成员中有空格时,其尾部的空格将自动被删除。
ENUM 值在内部用整数表示,并且每个枚举值均有一个索引值: 列表值所允许的成员值从 1 开始编号,MySQL 存储的就是这个索引编号。枚举最多可以有 65535 个元素。

例如,定义 ENUM 类型的列('first', 'second', 'third'),该列可以取的值和每个值的索引如表所示:

索引
NULL NULL
'' 0
first 1
second 2
third 3

ENUM 值依照列索引顺序排列,并且空字符串在非空字符串前,NULL 值排在其他所有的枚举值前。

在这里,有一个方法可以查看列成员的索引值

例: 创建表 tmp9,定义 ENUM 类型的列 enum('first', 'second', 'third'),查看列成员的索引值,SQL 语句如下:

1
2
3
CREATE TABLE tmp9 (
    enum ENUM('first','second','third')
);
1
INSERT INTO tmp9 values('first'),('second'),('third'),(NULL);

查看索引值:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
mysql> SELECT enum, enum+0 FROM tmp9;
+--------+--------+
| enum   | enum+0 |
+--------+--------+
| first  |      1 |
| second |      2 |
| third  |      3 |
| NULL   |   NULL |
+--------+--------+
4 rows in set (0.00 sec)

提示
ENUM 列总有一个默认值: 如果将 ENUM 列声明为 NULL,NULL 值则为该列的一个有效值,并且默认值为 NULL;
如果 ENUM 列被声明为 NULL,其默认值为允许的值列表的第 1 个元素。

例: 创建表 tmp10,定义 INT 类型的 soc 字段,ENUM 类型的字段 level,并且列表值为 ('excellent','good','bad'),向表 tmp10 中插入数据 (70,'good')、(90,1)、(75,2)、(50,3)、(100,'best'),SQL 语句如下:

1
2
3
4
CREATE TABLE tmp10 (
    soc INT,
    level enum('excellent','good','bad')
);

插入数据:

1
INSERT INTO tmp10 values(70,'good'),(90,1),(75,2),(50,3);

再次插入数据:

1
INSERT INTO tmp10 values(100,'best');
1
2
mysql> INSERT INTO tmp10 values(100,'best');
ERROR 1265 (01000): Data truncated for column 'level' at row 1

这里系统提示错误,可以看到,由于字符串值 'best' 不在 ENUM 列表中,所以对数据进行了阻止插入操作,查询结果如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
mysql> SELECT * FROM tmp10;
+------+-----------+
| soc  | level     |
+------+-----------+
|   70 | good      |
|   90 | excellent |
|   75 | good      |
|   50 | bad       |
+------+-----------+
4 rows in set (0.00 sec)

由结果可以看到,因为 ENUM 列表中的值在 MySQL 中都是以编号序列存储的,所以插入列表中的值 "good" 或者插入其对应序列 '2' 的结果是相同的。

SET 类型

SET 是一个字符串对象,可以有零或多个值。
SET 列最多可以有 64 个成员,其值为表创建时规定的一列值。
指定包括多个 SET 成员的 SET 列值,各成员之间用逗号(,)间隔开。语法格式如下:

1
SET('值1','值2',...,'值n')

与 ENUM 类型相同,SET 值在内部用整数表示,列表中每一个值都有一个索引编号。
当创建表时,SET 成员值的尾部空格将自动被删除。
与 ENUM 类型不同的是,ENUM 类型的字段只能从定义的列值中选择一个值插入,而 SET 类型的列可从定义的列值中选择多个字符的联合。

如果插入 SET 字段中列值有重复,则 MySQL 自动删除重复的值;
插入 SET 字段的值的顺序并不重要,MySQL 会在存入数据库时按照定义的顺序显示;
如果插入了不正确的值,默认情况下,MySQL 将忽视这些值,并给出警告。

例: 创建表 tmp11,定义 SET 类型的字段 s,取值列表为('a','b','c','d'),插入数据('a')、('a,b,a'、('c,a,d')、('a,x,b,y'),SQL 语句如下:

1
2
3
CREATE TABLE tmp11 (
    s SET('a', 'b', 'c', 'd')
);

插入数据:

1
INSERT INTO tmp11 values('a'),('a,b,a'),('c,a,d');

再次插入数据:

1
2
mysql> INSERT INTO tmp11 values('a,x,b,y');
ERROR 1265 (01000): Data truncated for column 's' at row 1
1
2
3
4
5
6
7
8
9
mysql> SELECT * FROM tmp11;
+-------+
| s     |
+-------+
| a     |
| a,b   |
| a,c,d |
+-------+
3 rows in set (0.00 sec)

从结果可以看到,对于 SET 来说,如果插入的值为重复的,则只取一个,例如插入 "a,b,a",则结果为 "a,b";
如果插入了不按顺序排列的值,则自动俺顺序插入,例如插入 "c,a,d",结果为 "a,c,d";
如果插入了不正确的值,那么该值将被阻止插入,例如插入值 "a,x,b,y"

二进制字符串类型

MySQL 中的二进制数据类型有 BIT、BINARY、VARBINARY、TINYBLOB、BLOB、MEDIUMBLOB 和 LONGBLOB

类型名称 说明 存储需求
BIT(M) 位字段类型 大约(M+7)/8字节
BINARY(M) 固定长度二进制字符串 M字节
VARBINARY(M) 可变长度二进制字符串 M+1字节
TINYBLOB(M) 非常小的 BLOB L+1字节,再次 L < 2^8
BLOB(M) 小 BLOB L+2字节,在此 L < 2^{16}
MEDIUMBLOB(M) 中等大小的 BLOB L+3字节,在此 L < 2^{24}
LONGBLOB(M) 非常大的 BLOB L+4 字节,在此 L < 2^{32}

BIT 类型

BINARY 和 VARBINARY 类型

BLOB 类型

如何选择数据类型

MySQL 提供了大量的数据类型,为了优化存储、提高数据库性能,在任何情况下均应使用最精确的类型,即在所有可以表示该列值的类型中,该类型使用的存储最少。

整数和浮点数

如果不需要小数部分,就是用整数来保存数据;如果需要表示小数部分,就使用浮点数类型。
对于浮点数列,存储的数据会对该列定义的小数位进行四舍五入。
例如,假设列的值的范围为 1 - 99999,若使用整数,则 MEDIUMINT UNSIGNED 是最好的类型;
若需要存储小数,则使用 FLOAT 类型

浮点类型包括 FLOAT 和 DOUBLE 类型。
DOUBLE 类型精度比 FLOAT 类型高,因此要求存储精度较高时应选择 DOUBLE 类型。

浮点数和定点数

浮点数 FLOAT、DOUBLE 相对于定点数 DECIMAL 的优势是: 在长度一定的情况下,浮点数能表示更大的数据范围。
由于浮点数容易产生误差,因此对精确度要求比较高,建议使用 DECIMAL 来存储。
DECIMAL 在 MySQL 中是以字符串存储的,用于定义货币等对精确度要求较高的数据。
在数据迁移中,float(M,D)是非标准 SQL 定义,数据库迁移可能会出现问题,最好不要这样使用。
另外,两个浮点数进行减法和比较运算时也容易出问题,因此在进行计算的时候,一定要小心。
进行数值比较时,最好使用 DECIMAL 类型。

日期与时间类型

MySQL 对于不同种类的日期和时间有很多数据类型,比如 YEAR 和 TIME。
如果只需要记录年份,则使用 YEAR 类型即可;如果只记录时间,则使用 TIME 类型。

如果同时需要记录日期和时间,则可以使用 TIMESTAMP 或者 DATETIME 类型。
由于 TIMESTAMP 列的取值范围小于 DATETIME 的取值范围,因此存储范围较大的日期最好使用 DATETIME

TIMESTAMP 也有一个 DATETIME 不具备的属性。
默认的情况下,当插入一条记录但并没有指定 TIMESTAMP 这个列值时,MySQL 会把 TIMESTAMP 列设为当前的时间。
因此当需要插入记录的同时插入当前时间时,使用 TIMESTAMP 时方便的。
另外,TIMESTAMP 在空间上 DATETIME 更有效。

CHAR 与 VARCHAR

CHAR 和 VARCHAR 的区别如下:

  • CHAR 是固定长度字符,VARCHAR 是可变长度字符
  • CHAR 会自动删除插入数据的尾部空格,VARCHAR 不会删除尾部空格

CHAR 是固定长度,所以它的处理速度比 VARCHAR 的速度要快,但是它的缺点是浪费存储空间,所以对存储不大但速度上有要求的可以使用 CHAR 类型,反之可以使用 VARCHAR 类型来实现。

存储引擎对于选择 CHAR 和 VARCHAR 的影响:

  • 对于 MyISAM 存储引擎: 最好使用固定长度的数据列代替可变长度的数据列。这样可以使整个表静态化,从而使数据检索更快,用空间换时间。
  • 对于 InnoDB 存储引擎: 使用可变长度的数据列,因为 InnoDB 数据表的存储格式不分固定长度和可变长度,因此使用 CHAR 不一定比使用 VARCHAR 更好,但由于 VARCHAR 是按照实际的长度存储的,比较节省空间,所以对磁盘 I/O 和数据存储总量比较好。

ENUM 和 SET

ENUM 只能取单值,它的数据列表是一个枚举集合。它的合法取值列表最多允许有 65535 个成员。
因此,在需要从多个值中选取一个时,可以使用 ENUM。
比如: 性别字段适合定义为 ENUM 类型,每次只能从 '男' 或 '女' 中取一个

SET 可取多值。它的合法取值列表最多允许有 64 个成员。空字符串也是一个合法的 SET 值。
在需要取多个值的时候,适合使用 SET 类型,比如要存储一个人的兴趣爱好,最好使用 SET 类型。

ENUM 和 SET 的值是以字符串形式出现的,但在内部,MySQL 是以数值的形式存储它们的。

BLOB 和 TEXT

BLOB 是二进制字符串,TEXT 是非二进制字符串,两者均可放大容量的信息。
BLOB 主要存储图片、音频信息等,而 TEXT 只能存储纯文本文件

运算符概述

运算符连接表达式中的各个操作数,其作用是用来指明对操作数所进行的运算。
运用运算符可以更加灵活地使用表中的数据,常见的运算符类型有算术运算符、比较运算符、逻辑运算符和位运算符。

运算符是告诉 MySQL 执行特定算术或逻辑操作的符号。
MySQL 的内部运算符很丰富,主要有四大类,分别是算术运算符、比较运算符、逻辑运算符、位运算符

算术运算符:
算术运算符用于各类数值运算,包括加(+)、减(-)、乘(*)、除(/)、求余(或称模运算,%)

比较运算符:
比较运算符用于表运算,包括大于(>)、小于(<)、等于(=)、大于等于(>=)、小于等于(<=)、不等于(!=),以及 INBETWEEN ANDIS NULLGREATESTLEASTLIKEREGEXP

逻辑运算符:
逻辑运算符的求值所得结果均为 1(TRUE)、0(FALSE),这类运算符有逻辑非(NOT 或者 !)、逻辑与(AND 或者 &&)、逻辑或 (OR 或者 ||)、逻辑异或(XOR)

位运算符:
位运算符参与运算的操作数按二进制按位进行运算,包括位与(&)、位或(|)、位非(~)、位异或(^)、左移(<<)、右移(>>)6种

算术运算符

运算符 作用
+ 加法运算
- 减法运算
* 乘法运算
/ 除法运算,返回商
% 求余运算,返回余数

例: 创建表 tmp14,定义数据类型为 INT 的字段 num,插入值 64,对 num 值进行算术运算

1
2
3
CREATE TABLE tmp14 (
    num INT
);
1
INSERT INTO tmp14 value(64);
1
2
3
4
5
6
7
8
SELECT num, num+10, num-3+5, num+5-3, num+36.5 FROM tmp14;

+------+--------+---------+---------+----------+
| num  | num+10 | num-3+5 | num+5-3 | num+36.5 |
+------+--------+---------+---------+----------+
|   64 |     74 |      66 |      66 |    100.5 |
+------+--------+---------+---------+----------+
1 row in set (0.01 sec)

例: 对 tmp14 表中的 num 进行乘法、除法运算

1
2
3
4
5
6
7
8
SELECT num, num*2, num /2, num / 3, num % 3 FROM tmp14;

+------+-------+---------+---------+---------+
| num  | num*2 | num /2  | num / 3 | num % 3 |
+------+-------+---------+---------+---------+
|   64 |   128 | 32.0000 | 21.3333 |       1 |
+------+-------+---------+---------+---------+
1 row in set (0.00 sec)

在数学运算时,除数为 0 的除法是没有意义的,因此除法运算中的除数不能为 0,如果被 0 除,则返回结果为 NULL

例: 用 0 除 num

1
2
3
4
5
6
7
8
SELECT num, num / 0, num % 0 FROM tmp14;

+------+---------+---------+
| num  | num / 0 | num % 0 |
+------+---------+---------+
|   64 |    NULL |    NULL |
+------+---------+---------+
1 row in set, 2 warnings (0.00 sec)

比较运算符

一个比较运算符的结果总是 1、0 或者是 NULL。
比较运算符经常在 SELECT 的查询条件子句中使用,用来查询满足指定条件的记录。

运算符 作用
= 等于
<=> 安全等于
<>(!=) 不等于
<= 小于等于
>= 大于等于
> 大于
IS NULL 判断一个值是否为 NULL
IS NOT NULL 判断一个值是否不为 NULL
LEAST 在有两个或多个参数时,返回最小值
GREATEST 当有两个或多个参数时,返回最大值
BETWEEN AND 判断一个值是否落在两个值之间
ISNULL 与 IS NULL 作用相同
IN 判断一个值是 IN 列表中的任意一个值
NOT IN 判断一个值不是 IN 列表中的任意一个值
LIKE 通配符匹配
REGEXP 正则表达式匹配

等于运算符(=)

等号(=)用来判断呢数字、字符串和表达式是否相等: 如果相等,返回值为 1,否则返回值为 0

例: 使用 '=' 进行相等判断,SQL 语句如下:

1
2
3
4
5
6
7
8
SELECT 1=0,'2'=2,2=2, '0.02'=0,'b'='b',(1+3)=(2+2),NULL=NULL;

+-----+-------+-----+----------+---------+-------------+-----------+
| 1=0 | '2'=2 | 2=2 | '0.02'=0 | 'b'='b' | (1+3)=(2+2) | NULL=NULL |
+-----+-------+-----+----------+---------+-------------+-----------+
|   0 |     1 |   1 |        0 |       1 |           1 |      NULL |
+-----+-------+-----+----------+---------+-------------+-----------+
1 row in set (0.01 sec)

由结果可以看到,在进行判断时,2=2 和 '2'=2 的返回值相同,都为 1.
因为在进行判断时,MySQL 自动进行了转换,把字符 '2' 转换成了数字 2;
由于 '=' 不能用于空值 NULL 的判断,因此返回值为 NULL

数值比较时有如下规则:
(1) 若有一个或两个参数为 NULL,则比较运算的结果为 NULL
(2) 若同一个比较运算中的两个参数都是字符串,则按照字符串进行比较
(3) 若两个参数均为整数,则按照整数进行比较
(4) 若用字符串和数字进行相等判断,则 MySQL 可以自动将字符串转换为数字。

安全等于运算符(<=>)

这个操作符和 = 操作符执行相同的比较操作,不过 <=> 可以用来判断 NULL 值。
在两个操作数均为 NULL 时,其返回值为 1,而不是 NULL;
当一个操作数为 NULL 时,其返回值为 0,而不为 NULL

例: 使用 '<=>' 进行相等的判断,SQL 语句如下:

1
2
3
4
5
6
7
8
SELECT 1 <=> 0, '2' <=> 2, 2 <=> 2, '0.02' <=> 0, 'b' <=> 'b', (1 + 3) <=> (2 + 1), NULL <=> NULL;

+---------+-----------+---------+--------------+-------------+---------------------+---------------+
| 1 <=> 0 | '2' <=> 2 | 2 <=> 2 | '0.02' <=> 0 | 'b' <=> 'b' | (1 + 3) <=> (2 + 1) | NULL <=> NULL |
+---------+-----------+---------+--------------+-------------+---------------------+---------------+
|       0 |         1 |       1 |            0 |           1 |                   0 |             1 |
+---------+-----------+---------+--------------+-------------+---------------------+---------------+
1 row in set (0.00 sec)

不等于运算符(<> 或者 !=)

'<>' 或者 '!=' 用于判断数字、字符串、表达式不相等的判断:如果不想等,返回值为 1;否则返回值为 0.
这两个运算符不能用于判断空值 NULL。

例: 使用 '<>' 和 '!=' 进行不相等的判断

1
SELECT 'good' <> 'god', 1 <> 2, 4 != 4, 5.5 != 5, (1+3)!=(2+1), NULL <> NULL;

小于等于运算符(<=)

'<=' 用来判断左边的操作数是否小于等于右边的操作数: 如果小于等于,返回值为 1;否则返回值为 0.
'<=' 不能用于判断空值 NULL

IS NULL(ISNULL)和 IS NOT NULL 运算符

IS NULL 和 ISNULL 检验一个值是否为 NULL;如果为 NULL,返回值为 1;否则返回值为 0.
IS NOT NULL 检验一个值是否为非 NULL: 如果是非 NULL,返回 1,否则返回 0

例:

1
2
3
4
5
6
7
8
SELECT NULL IS NULL, ISNULL(NULL), ISNULL(10), 10 is NOT NULL;

+--------------+--------------+------------+----------------+
| NULL IS NULL | ISNULL(NULL) | ISNULL(10) | 10 is NOT NULL |
+--------------+--------------+------------+----------------+
|            1 |            1 |          0 |              1 |
+--------------+--------------+------------+----------------+
1 row in set (0.01 sec)

BETWEEN AND

语法格式为: expr BETWEEN min AND max
假如 expr 大于等于 min 且小于等于 max,则 BETWEEN 的返回值为 1,否则返回值为 0

例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
SELECT 4 BETWEEN 2 AND 5, 4 BETWEEN 4 AND 6, 12 BETWEEN 9 AND 10;

+-------------------+-------------------+---------------------+
| 4 BETWEEN 2 AND 5 | 4 BETWEEN 4 AND 6 | 12 BETWEEN 9 AND 10 |
+-------------------+-------------------+---------------------+
|                 1 |                 1 |                   0 |
+-------------------+-------------------+---------------------+
1 row in set (0.02 sec)

SELECT 'x' BETWEEN 'f' AND 'g', 'b' BETWEEN 'a' AND 'c';

+-------------------------+-------------------------+
| 'x' BETWEEN 'f' AND 'g' | 'b' BETWEEN 'a' AND 'c' |
+-------------------------+-------------------------+
|                       0 |                       1 |
+-------------------------+-------------------------+
1 row in set (0.00 sec)

LEAST 运算符

语法格式为: LEAST(值1,值2,...,值n)。其中, "值n" 表示参数列表中有 n 个值。
在有两个或多个参数的情况下,返回最小值。
假如任意一个自变量为 NULL,则 LEAST() 的返回值为 NULL

例:

1
2
3
4
5
6
7
8
SELECT LEAST(2, 0),LEAST(20.0,3.0,100.5),LEAST('a','c','b'),LEAST(10,NULL);

+-------------+-----------------------+--------------------+----------------+
| LEAST(2, 0) | LEAST(20.0,3.0,100.5) | LEAST('a','c','b') | LEAST(10,NULL) |
+-------------+-----------------------+--------------------+----------------+
|           0 |                   3.0 | a                  |           NULL |
+-------------+-----------------------+--------------------+----------------+
1 row in set (0.02 sec)

GREATEST

语法格式为: GREATE(值1,值2,...,值n)。其中,n 表示参数列表有 n 个值。
当有两个或多个参数时,返回值为最大值。假如任意一个自变量为 NULL,则 GREATEST() 返回值为 NULL

IN、NOT IN 运算符

IN 运算符用来判断操作数是否为 IN 列表中的其中一个值: 如果是,返回值为1;否则返回值为 0.
NOT IN 与其相反。

例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
SELECT 2 IN (1, 3, 5,'thks'), 'thks' IN (1, 3, 5, 'thks');

+-----------------------+-----------------------------+
| 2 IN (1, 3, 5,'thks') | 'thks' IN (1, 3, 5, 'thks') |
+-----------------------+-----------------------------+
|                     0 |                           1 |
+-----------------------+-----------------------------+
1 row in set, 2 warnings (0.02 sec)

SELECT 2 NOT IN (1, 3, 5,'thks'), 'thks' NOT IN (1, 3, 5, 'thks');

+---------------------------+---------------------------------+
| 2 NOT IN (1, 3, 5,'thks') | 'thks' NOT IN (1, 3, 5, 'thks') |
+---------------------------+---------------------------------+
|                         1 |                               0 |
+---------------------------+---------------------------------+
1 row in set, 2 warnings (0.00 sec)

在左侧表达式为 NULL 的情况下,或是表中找不到匹配项并且表中一个表达式为 NULL 的情况下,IN 的返回值为 NULL。

例:

1
2
3
4
5
6
7
8
SELECT NULL IN (1,3,5,'thks'), 10 IN (1,3,NULL,'thks');

+------------------------+-------------------------+
| NULL IN (1,3,5,'thks') | 10 IN (1,3,NULL,'thks') |
+------------------------+-------------------------+
|                   NULL |                    NULL |
+------------------------+-------------------------+
1 row in set, 1 warning (0.00 sec)

LIKE

LIKE 运算符用来匹配字符串,语法格式为: expr LIKE 匹配条件
如果 expr 满足匹配条件,则返回值为 1(TRUE);如果不匹配,则返回值为 0(FALSE)。
expr 或匹配条件中任何一个为 NULL,则结果为 NULL

LIKE 运算符在进行匹配时,可以使用下面的两种通配符:
(1) '%',匹配任何数目的字符,甚至包括零字符
(2) '_',只能匹配一个字符

例:

1
2
3
4
5
6
7
8
SELECT 'stud' LIKE 'stud', 'stud' LIKE 'stu_', 'stud' LIKE '%d', 'stud' LIKE 't___', 's' LIKE NULL;

+--------------------+--------------------+------------------+--------------------+---------------+
| 'stud' LIKE 'stud' | 'stud' LIKE 'stu_' | 'stud' LIKE '%d' | 'stud' LIKE 't___' | 's' LIKE NULL |
+--------------------+--------------------+------------------+--------------------+---------------+
|                  1 |                  1 |                1 |                  0 |          NULL |
+--------------------+--------------------+------------------+--------------------+---------------+
1 row in set (0.01 sec)

REGEXP

REGEXP 运算符用来匹配字符串,语法格式为: expr REGEXP 匹配条件
如果 expr 满足匹配条件,返回 1;如果不满足,则返回 0.
若 expr 或匹配条件任意一个为 NULL,则结果为 NULL。

REGEXP 运算符在进行匹配时,常用的有下面几种通配符:

(1) ^ 匹配以该字符后面的字符开头的字符串
(2) $ 匹配以该字符后面的字符结尾的字符串
(3) . 匹配任何一个单字符
(4) [...] 匹配在方括号内的任何字符。例如,[abc] 匹配 a bc
为了命名字符的范围,使用一个 -[a-z] 匹配 26 个小写字母,而 [0-9] 匹配任何数字
(5) * 匹配零个或多个在它前面的字符。例如 x* 匹配你任何数量的 x 字符,[0-9]* 匹配任何数量的数字,而 * 匹配任何数量的任何字符

例:

1
2
3
4
5
6
7
8
SELECT 'ssky' REGEXP '^s', 'ssky' REGEXP 'y$', 'ssky' REGEXP '.sky', 'ssky' REGEXP '[ab]';

+--------------------+--------------------+----------------------+----------------------+
| 'ssky' REGEXP '^s' | 'ssky' REGEXP 'y$' | 'ssky' REGEXP '.sky' | 'ssky' REGEXP '[ab]' |
+--------------------+--------------------+----------------------+----------------------+
|                  1 |                  1 |                    1 |                    0 |
+--------------------+--------------------+----------------------+----------------------+
1 row in set (0.13 sec)

逻辑运算符

在 SQL 中,所有逻辑运算符的求值所得结果均为 TRUE、FALSE 或 NULL。
在 MySQL 中,它们体现为 1(TRUE)、0(FALSE) 和 NULL。

运算符 作用
NOT 或者 ! 逻辑非
AND 或者 && 逻辑与
OR 或者 || 逻辑或
XOR 逻辑异或

NOT 或者 !

逻辑非运算符 表示当操作数为 0 时,所得值为 1; 当操作数为非零值时,所得值为 0;
当操作数为 NULL 时,所得的返回值为 NULL

例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
SELECT NOT 10, NOT (1-1), NOT -5, NOT NULL, NOT 1 + 1;

+--------+-----------+--------+----------+-----------+
| NOT 10 | NOT (1-1) | NOT -5 | NOT NULL | NOT 1 + 1 |
+--------+-----------+--------+----------+-----------+
|      0 |         1 |      0 |     NULL |         0 |
+--------+-----------+--------+----------+-----------+
1 row in set (0.02 sec)

SELECT !10, !(1-1), !-5, ! NULL, ! 1 + 1;

+-----+--------+-----+--------+---------+
| !10 | !(1-1) | !-5 | ! NULL | ! 1 + 1 |
+-----+--------+-----+--------+---------+
|   0 |      1 |   0 |   NULL |       1 |
+-----+--------+-----+--------+---------+
1 row in set, 5 warnings (0.00 sec)

SELECT ! 1+1;

+-------+
| ! 1+1 |
+-------+
|     1 |
+-------+
1 row in set, 1 warning (0.00 sec)

由结果可以看到,前 4 列 "NOT" 和 "!" 的返回值都相同。为什么最后 1 列回出现不同的值呢?
这是因为 "NOT" 与 "!" 的优先级不同。"NOT" 的优先级低于 "+",因此 "NOT 1 + 1" 相当于 "NOT (1+1)",先计算 "1+1",然后再进行 NOT 运算,因为操作数不为 0,所以结果是 0;
相反,"!" 的优先级要高于 "+" 运算,因此 "! 1+1" 相当于 "(!1) + 1",最后结果为 1

提示:
在使用运算符运算时,一定要注意不同运算符的优先级不同。如果不能确定计算顺序,最好使用括号,以保证运算结果的正确。

AND 或者 &&

逻辑与运算符 表示当所有操作数均为非零值并且不为 NULL 时,计算所得结果为 1;当一个或多个操作数为 0 时,所得结果为 0;其余情况返回值为 NULL

例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
SELECT 1 AND -1, 1 AND 0, 1 AND NULL, 0 AND NULL;

+----------+---------+------------+------------+
| 1 AND -1 | 1 AND 0 | 1 AND NULL | 0 AND NULL |
+----------+---------+------------+------------+
|        1 |       0 |       NULL |          0 |
+----------+---------+------------+------------+
1 row in set (0.02 sec)

SELECT 1 && -1, 1 && 0, 1 && NULL, 0 && NULL;
+---------+--------+-----------+-----------+
| 1 && -1 | 1 && 0 | 1 && NULL | 0 && NULL |
+---------+--------+-----------+-----------+
|       1 |      0 |      NULL |         0 |
+---------+--------+-----------+-----------+
1 row in set, 4 warnings (0.01 sec)

OR 或者 ||

逻辑或运算符 表示当两个操作数均为非 NULL 且任意一个操作数为非零值时,结果为 1, 否则为 0;
当有一个操作数为 NULL,且另一个操作数为非零值时,则结果为 1,否则结果为 NULL;
当两个操作数均为 NULL 时,则所得结果为 NULL

例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
SELECT 1 OR -1 OR 0, 1 OR 2, 1 OR NULL, 0 OR NULL, NULL OR NULL;

+--------------+--------+-----------+-----------+--------------+
| 1 OR -1 OR 0 | 1 OR 2 | 1 OR NULL | 0 OR NULL | NULL OR NULL |
+--------------+--------+-----------+-----------+--------------+
|            1 |      1 |         1 |      NULL |         NULL |
+--------------+--------+-----------+-----------+--------------+
1 row in set (0.01 sec)

SELECT 1 || -1 || 0, 1 || 2, 1 || NULL, 0 || NULL, NULL || NULL;

+--------------+--------+-----------+-----------+--------------+
| 1 || -1 || 0 | 1 || 2 | 1 || NULL | 0 || NULL | NULL || NULL |
+--------------+--------+-----------+-----------+--------------+
|            1 |      1 |         1 |      NULL |         NULL |
+--------------+--------+-----------+-----------+--------------+
1 row in set, 6 warnings (0.00 sec)

XOR

逻辑异或运算符 XOR 表示当任意一个操作数为 NULL 时,返回值为 NULL;
对于非 NULL 的操作数,如果两个操作数都是非 0 值或都是 0 值,则返回结果为 0;
如果一个为 0 值,另一个非零值,返回结果为 1

例:

1
2
3
4
5
6
7
8
SELECT 1 XOR 1, 0 XOR 0, 1 XOR 0, 1 XOR NULL, 1 XOR 1 XOR 1;

+---------+---------+---------+------------+---------------+
| 1 XOR 1 | 0 XOR 0 | 1 XOR 0 | 1 XOR NULL | 1 XOR 1 XOR 1 |
+---------+---------+---------+------------+---------------+
|       0 |       0 |       1 |       NULL |             1 |
+---------+---------+---------+------------+---------------+
1 row in set (0.00 sec)

位运算符

位运算符是在二进制数上进行计算的运算符。
位运算符会先将操作数变成二进制数,然后进行位运算,最后将计算结果从二进制变回十进制。
MySQL 中提供的位运算符有按位或(|)、按位与(&)、按位异或(^)、按位左移(<<)、按位右移(>>)和按位取反(~)

运算符 作用
| 位或
& 位与
^ 位异或
<< 位左移
>> 位右移
~ 位取反,反转所有比特

位或运算符(|)

位或运算的实质是将参与运算的几个数据按照对应的二进制数逐位进行逻辑或运算。
对应的二进制位有一个或两个为 1 则该位的运算结果为 1,否则为 0

例:

1
2
3
4
5
6
7
8
SELECT 10 | 15, 9 | 4 | 2;

+---------+-----------+
| 10 | 15 | 9 | 4 | 2 |
+---------+-----------+
|      15 |        15 |
+---------+-----------+
1 row in set (0.01 sec)

位与运算符(&)

位与运算的实质是将参与运算的几个操作数按照对应的二进制数逐位进行逻辑与运算。
对应的二进制位都为 1 则该位的运算结果位 1,否则为 0.

1
2
3
4
5
6
7
8
SELECT 10 & 15, 9 & 4 & 2;

+---------+-----------+
| 10 & 15 | 9 & 4 & 2 |
+---------+-----------+
|      10 |         0 |
+---------+-----------+
1 row in set (0.01 sec)

结果为一个 64 位无符号整数

位异或运算符(^)

位异或运算的实质是将参与运算的两个数据按照对应的二进制数逐位进行逻辑异或运算。
对应位的二进制数不同时,对应位的结果才为 1.
如果两个对应位数都为 0 或这都为 1,则对应位的结果为 0

例:

1
2
3
4
5
6
7
8
SELECT 10 ^ 15, 1 ^ 0, 1 ^ 1;

+---------+-------+-------+
| 10 ^ 15 | 1 ^ 0 | 1 ^ 1 |
+---------+-------+-------+
|       5 |     1 |     0 |
+---------+-------+-------+
1 row in set (0.00 sec)

位左移运算符(<<)

位左移运算符使指定的二进制值的所有位都左移指定的位数。
左移指定位数之后,左边高位的数值将被移出并丢弃,右边低位空位的位置用 0 补齐。
语法格式为: expr << n。其中,n 指定 expr 要移位的位数

例:

1
2
3
4
5
6
7
8
SELECT 1 << 2, 4 << 2;

+--------+--------+
| 1 << 2 | 4 << 2 |
+--------+--------+
|      4 |     16 |
+--------+--------+
1 row in set (0.00 sec)

位右移运算符(>>)

位右移运算符使指定的二进制值的所有位都右移指定的位数。
右移指定位数之后,右边低位的数值将被移出并丢弃,左边高位空出的位置用 0 补齐。
语法格式为: expr >> n。其中,n 指定值 expr 要移位的位数

例:

1
2
3
4
5
6
7
8
SELECT 1 >> 1, 16 >> 2;

+--------+---------+
| 1 >> 1 | 16 >> 2 |
+--------+---------+
|      0 |       4 |
+--------+---------+
1 row in set (0.00 sec)

位取反运算符(~)

位取反运算的实质是将参与运算的数据按照对应的二进制数逐位反转,即 1 取反后变为 0、0 取反后变为 1.

1
2
3
4
5
6
7
8
SELECT 5 & ~1;

+--------+
| 5 & ~1 |
+--------+
|      4 |
+--------+
1 row in set (0.01 sec)

在逻辑运算 5 & ~1 中,由于位取反运算符 ~ 的级别高于位与运算符 &,因此先对 1 进行取反操作,取反之后,除了最低位位 0 外其他位都为 1,然后再与 5 进行与运算

提示:
MySQL 经过位运算之后的数值是一个 64 位的无符号整数,1 的二进制数值表示位最右边位位 1、其他位均为 0,取反操作之后,除了最低位为 0 外,其他位均变为 1.

可以使用 BIN() 函数查看 1 取反之后的结果:

1
2
3
4
5
6
7
8
SELECT BIN(~1);

+------------------------------------------------------------------+
| BIN(~1)                                                          |
+------------------------------------------------------------------+
| 1111111111111111111111111111111111111111111111111111111111111110 |
+------------------------------------------------------------------+
1 row in set (0.01 sec)

专家解惑

疑问1: 在 MySQL 中如何使用特殊字符?

单引号(')、双引号(")、反斜线(\)等在 MySQL 中是不能直接输入使用的,否则回产生意料之外的结果。
在 MySQL 中,这些特殊字符称为转义字符,在输入时需要以反斜线符号(\)开头,所以在使用单引号和双引号时应分别输入(\')或者(\"),输入反斜线时应该输入(\\),其他特殊字符还有回车符(\r)、换行符(\n)、制表符(\tab)、退格符(\b)等。
在向数据库中插入这些特殊字符时,一定要进行转义处理。

疑问2: 在 MySQL 中可以存储文件吗?

MySQL 中的 BLOB 和 TEXT 字段类型可以存储数据量较大的文件,比如存储图像、声音或者是大容量的文本内容(例如网页或者文档)

虽然使用 BLOB 或者 TEXT 可以存储大容量的数据,但是对这些字段的处理回降低数据库的性能。如果并非必要,可以选择只存储文件路径。

疑问3: 在 MySQL 中如何执行区分大小写的字符串比较?

在 Windows 平台上,MySQL 是不区分大小写的,因此字符串比较函数也不区分大小写。
如果想执行区分大小写的比较,可以在字符串前面添加 BINARY 关键字。
例如,默认情况下,'a' = 'A' 的返回结果为 1,如果使用 BINARY 关键字,即 BINARY 'a' = 'A',则结果为 0.
在区分大小写的情况下,'a' 与 'A' 并不相同