Skip to content
On this page

表达式和函数

表达式

操作数

MySQL中操作数可以是下边这几种类型:

  1. 常数常数很好理解,我们平时用到的数字、字符串、时间值什么的都可以被称为常数,它是一个确定的值,比如数字1,字符串'abc',时间值2019-08-16 17:10:43啥的。
  2. 列名针对某个具体的表,它的列名可以被当作表达式的一部分,比如对于student_info表来说,number、name都可以作为操作数。
  3. 函数调用MySQL中有函数的概念,比方说获取当前时间的函数NOW,而在函数后边加个小括号就算是一个函数调用,比如NOW()。如果你不清楚函数的概念,我们之后会详细唠叨的,现在不知道也可以~
  4. 标量子查询或者行子查询这个子查询我们稍后会详细唠叨的~
  5. 其他表达式一个表达式也可以作为一个操作数与另一个操作数来形成一个更复杂的表达式,比方说(假设col是一个列名):
    • (col - 5) / 3
    • (1 + 1) 2 + col 3

操作符

  • 算术操作符就是加减乘除法那一堆,我们看一下MySQL中都支持哪些:在使用MySQL中的算术操作符时需要注意,DIV和/都表示除法操作符,但是DIV只会取商的整数部分,/会保留商的小数部分。比如表达式 2 DIV 3的结果是0,而2 / 3的结果是0.6667。 | 操作符 | 示例 | 描述 | | --- | --- | --- | | + | a + b | 加法 | | - | a - b | 减法 | | | a b | 乘法 | | / | a / b | 除法 | | DIV | a DIV b | 除法,取商的整数部分 | | % | a % b | 取余 | | - | -a | 负号 |

  • 比较操作符

就是在搜索条件中我们已经看过的比较操作符,我们把常用的都抄下来看一下:

操作符示例描述
=a = ba等于b
<>或者!=a <> ba不等于b
<a < ba小于b
<=a <= ba小于或等于b
>a > ba大于b
>=a >= ba大于或等于b
BETWEENa BETWEEN b AND c满足 b <= a <= c
NOT BETWEENa NOT BETWEEN b AND c不满足 b <= a <= c
INa IN (b1, b2, ...)a是b1, b2, ... 中的某一个
NOT INa NOT IN (b1, b2, ...)a不是b1, b2, ... 中的任意一个
IS NULLa IS NULLa的值是NULL
IS NOT NULLa IS NOT NULLa的值不是NULL
LIKEa LIKE ba匹配b
NOT LIKEa NOT LIKE ba不匹配b

由比较操作符连接而成的表达式也称为布尔表达式,表示真或者假,也可以称为TRUE或者FALSE。比如1 > 3就代表FALSE,3 != 2就代表TRUE。

  • 逻辑操作符

逻辑操作符是用来将多个布尔表达式连接起来,我们需要了解这几个逻辑操作符:

操作符示例描述
ANDa AND b只有a和b同时为真,表达式才为真
ORa OR b只要a或b有任意一个为真,表达式就为真
XORa XOR ba和b有且只有一个为真,表达式为真

表达式的使用

  • 放在查询中

可以在查询student_score表时把score字段的数据都加50

sql
mysql> select number,subject,score+50 from student_score;
+----------+-----------------------------+----------+
| number   | subject                     | score+50 |
+----------+-----------------------------+----------+
| 20180101 | 母猪的产后护理              |      128 |
| 20180101 | 论萨达姆的战争准备          |      138 |
| 20180102 | 母猪的产后护理              |      150 |
| 20180102 | 论萨达姆的战争准备          |      148 |
| 20180103 | 母猪的产后护理              |      109 |
| 20180103 | 论萨达姆的战争准备          |      111 |
| 20180104 | 母猪的产后护理              |      105 |
| 20180104 | 论萨达姆的战争准备          |       96 |
+----------+-----------------------------+----------+
8 rows in set (0.02 sec)

mysql>
  • 作为搜索条件

函数

文本处理函数

名称调用示例示例结果描述
LEFTLEFT('abc123', 3)abc给定字符串从左边取指定长度的子串
RIGHTRIGHT('abc123', 3)123给定字符串从右边取指定长度的子串
LENGTHLENGTH('abc')3给定字符串的长度
LOWERLOWER('ABC')abc给定字符串的小写格式
UPPERUPPER('abc')ABC给定字符串的大写格式
LTRIMLTRIM(' abc')abc给定字符串左边空格去除后的格式
RTRIMRTRIM('abc ')abc给定字符串右边空格去除后的格式
SUBSTRINGSUBSTRING('abc123', 2, 3)bc1给定字符串从指定位置截取指定长度的子串
CONCATCONCAT('abc', '123', 'xyz')abc123xyz将给定的各个字符串拼接成一个新字符串

以 CONCAT 函数组合查询

sql
mysql> select concat("学号", number, "的学生在课程", subject, "的分数是", score) from student_score;
+--------------------------------------------------------------------------------+
| concat("学号", number, "的学生在课程", subject, "的分数是", score)             |
+--------------------------------------------------------------------------------+
| 学号20180101的学生在课程母猪的产后护理的分数是78                               |
| 学号20180101的学生在课程论萨达姆的战争准备的分数是88                           |
| 学号20180102的学生在课程母猪的产后护理的分数是100                              |
| 学号20180102的学生在课程论萨达姆的战争准备的分数是98                           |
| 学号20180103的学生在课程母猪的产后护理的分数是59                               |
| 学号20180103的学生在课程论萨达姆的战争准备的分数是61                           |
| 学号20180104的学生在课程母猪的产后护理的分数是55                               |
| 学号20180104的学生在课程论萨达姆的战争准备的分数是46                           |
+--------------------------------------------------------------------------------+
8 rows in set (0.00 sec)

mysql>

日期和时间处理函数

名称调用示例示例结果描述
NOWNOW()2019-08-16 17:10:43返回当前日期和时间
CURDATECURDATE()2019-08-16返回当前日期
CURTIMECURTIME()17:10:43返回当前时间
DATEDATE('2019-08-16 17:10:43')2019-08-16将给定日期和时间值的日期提取出来
DATE_ADDDATE_ADD('2019-08-16 17:10:43', INTERVAL 2 DAY)2019-08-18 17:10:43将给定的日期和时间值添加指定的时间间隔
DATE_SUBDATE_SUB('2019-08-16 17:10:43', INTERVAL 2 DAY)2019-08-14 17:10:43将给定的日期和时间值减去指定的时间间隔
DATEDIFFDATEDIFF('2019-08-16', '2019-08-17');-1返回两个日期之间的天数(负数代表前一个参数代表的日期比较小)
DATE_FORMATDATE_FORMAT(NOW(),'%m-%d-%Y')08-16-2019用给定的格式显示日期和时间

在使用这些函数时需要注意一些地方:

  • 在使用DATE_ADD和DATE_SUB这两个函数时需要注意,增加或减去的时间间隔单位可以自己定义,下边是MySQL支持的一些时间单位: | 时间单位 | 描述 | | --- | --- | | MICROSECOND | 毫秒 | | SECOND | 秒 | | MINUTE | 分钟 | | HOUR | 小时 | | DAY | 天 | | WEEK | 星期 | | MONTH | 月 | | QUARTER | 季度 | | YEAR | 年 |

如果我们相让 2019-08-16 17:10:43 这个时间值增加2分钟,可以这么写:

sql
mysql> select date_add("2019-08-16 17:10:43", interval 2 minute);
+----------------------------------------------------+
| date_add("2019-08-16 17:10:43", interval 2 minute) |
+----------------------------------------------------+
| 2019-08-16 17:12:43                                |
+----------------------------------------------------+
1 row in set (0.00 sec)

mysql>

在使用 DATE_FORMAT 函数时需要注意,我们可以通过一些所谓的格式符来自定义日期和时间的显示格式,下边是MySQL中常用的一些日期和时间的格式符以及它们对应的含义:

格式符描述
%b简写的月份名称(Jan、Feb、...、Dec)
%D带有英文后缀的月份中的日期(0th、1st、2nd、...、31st))
%d数字格式的月份中的日期(00、01、02、...、31)
%f微秒(000000-999999)
%H二十四小时制的小时 (00-23)
%h十二小时制的小时 (01-12)
%i数值格式的分钟(00-59)
%M月份名(January、February、...、December)
%m数值形式的月份(00-12)
%p上午或下午(AM代表上午、PM代表下午)
%S秒(00-59)
%s秒(00-59)
%W星期名(Sunday、Monday、...、Saturday)
%w周内第几天 (0=星期日、1=星期一、 6=星期六)
%Y4位数字形式的年(例如2019)
%y2位数字形式的年(例如19)

我们可以把我们想要的显示格式用对应的格式符描述出来

sql
mysql> select date_format(now(), "%b %d %Y %h");
+-----------------------------------+
| date_format(now(), "%b %d %Y %h") |
+-----------------------------------+
| Jun 01 2021 09                    |
+-----------------------------------+
1 row in set (0.00 sec)

mysql>

数值处理函数

下边列举一些数学上常用到的函数,在遇到需要数学计算的业务时会很有用:

名称调用示例示例结果描述
ABSABS(-1)1取绝对值
PiPI()3.141593返回圆周率
COSCOS(PI())-1返回一个角度的余弦
EXPEXP(1)2.718281828459045返回e的指定次方
MODMOD(5,2)1返回除法的余数
RANDRAND()0.7537623539136372返回一个随机数
SINSIN(PI()/2)1返回一个角度的正弦
SQRTSQRT(9)3返回一个数的平方根
TANTAN(0)0返回一个角度的正切

聚集函数

函数名描述
COUNT返回某列的行数
MAX返回某列的最大值
MIN返回某列的最小值
SUM返回某列值之和
AVG返回某列的平均值

COUNT函数

COUNT函数使用来统计行数的,它有下边两种使用方式:

  • COUNT(*):对表中行的数目进行计数,不管列的值是不是NULL。
  • COUNT(列名):对特定的列进行计数,会忽略掉该列为NULL的行。

两者的区别是会不会忽略统计列的值为NULL的行!两者的区别是会不会忽略统计列的值为NULL的行!两者的区别是会不会忽略统计列的值为NULL的行!重要的事情说了3遍,希望你能记住。我们来数一下student_info表中有几行记录吧:

sql
mysql> select count(*) from student_info;
+----------+
| count(*) |
+----------+
|        6 |
+----------+
1 row in set (0.09 sec)

mysql>

MAX MIN 函数

取表列中最大值,最小值

sql
mysql> select max(score) from student_score;
+------------+
| max(score) |
+------------+
|        100 |
+------------+
1 row in set (0.00 sec)

mysql> select min(score) from student_score;
+------------+
| min(score) |
+------------+
|         46 |
+------------+
1 row in set (0.00 sec)

mysql>

SUM 函数

求列的和

sql
mysql> select sum(score) from student_score;
+------------+
| sum(score) |
+------------+
|        585 |
+------------+
1 row in set (0.00 sec)

mysql>

AVG 函数

求平均数函数

sql
mysql> select avg(score) from student_score;
+------------+
| avg(score) |
+------------+
|    73.1250 |
+------------+
1 row in set (0.00 sec)

mysql>

给定搜索条件聚焦函数使用

sql
mysql> select avg(score) from student_score where subject like "%产后护理%";
+------------+
| avg(score) |
+------------+
|    73.0000 |
+------------+
1 row in set (0.00 sec)

mysql>

聚焦函数 DISTINCT 使用

指定的列中有重复数据的话,可以选择使用DISTINCT来过滤掉这些重复数据

sql
mysql> select count(distinct major) from student_info;
+-----------------------+
| count(distinct major) |
+-----------------------+
|                     4 |
+-----------------------+
1 row in set (0.00 sec)

mysql>

可以看到总共只有 4 个科目

组合聚焦函数

sql
mysql> select count(*) as 成绩记录总数, max(score) as 最高成绩,min(score) as 最低成绩 from student_score;
+--------------------+--------------+--------------+
| 成绩记录总数       | 最高成绩     | 最低成绩     |
+--------------------+--------------+--------------+
|                  8 |          100 |           46 |
+--------------------+--------------+--------------+
1 row in set (0.00 sec)

mysql>

隐式类型转换

sql
mysql> select 1+2, "1"+2,"1"+"2";
+-----+-------+---------+
| 1+2 | "1"+2 | "1"+"2" |
+-----+-------+---------+
|   3 |     3 |       3 |
+-----+-------+---------+
1 row in set (0.00 sec)

mysql>

将函数参数转换为该函数期望的类型。

我们拿用于拼接字符串的CONCAT函数举例,这个函数以字符串类型的值作为参数,如果我们在调用这个函数的时候,传入了别的类型的值作为参数,MySQL会自动把这些值的类型转换为字符串类型的:

sql
CONCAT('1', '2')    →   '12'
CONCAT('1', 2)      →   '12'
CONCAT(1, 2)        →   '12'

虽然1、2都是数字,但是如果它们作为CONCAT函数的参数的话,都会被强制转换为字符串,所以上边几个表达式其实都会被当作CONCAT('1', '2)去处理的,这些表达式被放到查询列表时的效果如下:

sql
mysql> SELECT CONCAT('1', '2'), CONCAT('1', 2), CONCAT(1, 2);
+------------------+----------------+--------------+
| CONCAT('1', '2') | CONCAT('1', 2) | CONCAT(1, 2) |
+------------------+----------------+--------------+
| 12               | 12             | 12           |
+------------------+----------------+--------------+
1 row in set (0.00 sec)

mysql>

存储数据时,把某个值转换为某个列需要的类型。

我们先新建一个简单的表t:

sql
CREATE TABLE t (
i1 TINYINT,
i2 TINYINT,
s VARCHAR(100)
);

这个表有三个列,列i1和i2是用来存储整数的,列s是用来存储字符串的,如果我们在存储数据的时候填入的不是期望的类型,就像这样:

sql
mysql> INSERT INTO t(i1, i2, s) VALUES('100', '100', 200);
Query OK, 1 row affected (0.01 sec)

mysql>

我们为列i1和i2填入的值是一个字符串值:'100',列s填入的值是一个整数值:200,虽然说类型都不对,但是由于隐式类型转换的存在,在插入数据的时候字符串'100'会被转型为整数100,整数200会被转型成字符串'200',所以最后插入成功,我们来看一下效果:

sql
mysql> SELECT * FROM t;
+------+------+------+
| i1   | i2   | s    |
+------+------+------+
|  100 |  100 | 200  |
+------+------+------+
1 row in set (0.00 sec)

mysql>

类型转换的注意事项

  • MySQL会尽量把值转换为表达式中需要的类型,而不是产生错误。

按理说 '23sfd' 这个字符串无法转换为数字,但是MySQL规定只要字符串的开头部分包含数字,那么就把这个字符串转换为开头的数字,如果开头并没有包含数字,那么将被转换成0,比方说这样:

sql
'23sfd'23
'2019-08-28'2019
'11:30:32'11
'sfd'0

看个例子:

sql
mysql> SELECT '23sfd' + 0, 'sfd' + 0;
+-------------+-----------+
| '23sfd' + 0 | 'sfd' + 0 |
+-------------+-----------+
|          23 |         0 |
+-------------+-----------+
1 row in set, 2 warnings (0.00 sec)

mysql>

不过需要注意的是,这种强制转换不能用于存储数据中,比方说这样:

sql
mysql> INSERT INTO t(i1, i2, s) VALUES('sfd', 'sfd', 'aaa');
ERROR 1366 (HY000): Incorrect integer value: 'sfd' for column 'i1' at row 1
mysql>

由于 i1 和 i2 列需要整数,而填入的字符串 'sfd' 并不能顺利的转为整数,所以报错了。

在运算时会自动提升操作数的类型。

我们知道不同数据类型能表示的数值范围是不一样的,在小的数据类型经过算数计算后得出的结果可能大于该可以表示的范围。比方说t表中有一条记录如下:

sql
mysql> SELECT * FROM t;
+------+------+------+
| i1   | i2   | s    |
+------+------+------+
|  100 |  100 | 200  |
+------+------+------+
1 row in set (0.00 sec)

mysql>

其中的 i1 列和 i2 列的类型都是 TINYINT,而 TINYINT 能表示的最大正整数是 127,如果我们把 i1 列的值和 i2 列的值相加会发生什么呢?请看:

sql
mysql> SELECT i1 + i2 FROM t;
+---------+
| i1 + i2 |
+---------+
|     200 |
+---------+
1 row in set (0.00 sec)

mysql>

可以看到最后的结果是 200,可是它已经超过 TINYINT 类型的表示范围了。其实在运算的过程中,MySQL自动将整数类型的操作数提升到了 BIGINT,这样就不会产生运算结果太大超过 TINYINT 能表示的数值范围的尴尬情况了。类似的,有浮点数的运算过程会把操作数自动转型为 DOUBLE 类型。