目录

  • 一、MySQL进阶查询
  • 1.1 常用查询
  • 1.1.1 按关键字排序
  • 1.1.2 对结果进行分组
  • 1.1.3 限制结果条目
  • 1.1.4 设置别名
  • 1.1.5 通配符
  • 1.1.6 子查询
  • 1.2 NULL值
  • 1.3 正则表达式
  • 1.3.1 以特定字符串开头的记录
  • 1.3.2 以特定字符串结尾的记录
  • 1.3.3 包含指定字符串的记录
  • 1.3.4 以“.”代替字符串中的任意一个字符的记录
  • 1.3.5 匹配包含或者关系的记录
  • 1.3.6 “*”匹配前面字符的任意多次
  • 1.3.7 “+”匹配前面字符至少一次
  • 1.3.8 匹配指定字符集中的任意一个
  • 1.4 运算符
  • 1.4.1 算术运算符
  • 1.4.2 比较运算符
  • 1.4.3 逻辑运算符
  • 1.5 连接查询
  • 1.5.1 创建表
  • 1.5.2 插入数据
  • 1.5.3 内连接
  • 1.5.4 左连接
  • 1.5.5 右连接
  • 二、 数据库函数
  • 2.1 数学函数
  • 2.2 聚合函数
  • 2.3 字符串函数
  • 2.4 日期时间函数
  • 三、存储过程
  • 3.1 存储过程简介
  • 3.2 创建存储过程
  • 3.3 修改存储过程
  • 3.4 删除存储过程


一、MySQL进阶查询

1.1 常用查询

1.1.1 按关键字排序

■使用ORDER BY语句来实现排序
■排序可针对一个或多个字段
■ASC:升序,默认排序方式
■DESC:降序

■ORDER BY的语法结构
SELECT column1,column2,…FROM table_name ORDER BY column1,column2,… ASC|DESC;

■ORDER BY 后面跟多个字段时,字段之间使用英文逗号隔开,优先级是按先后顺序而定:
ORDER BY A,B desc 指A用升序,B用降序;
ORDER BY A asc,B desc 指A用升序,B用降序;
ORDER BY A desc,B desc 指A用降序,B用降序;

■进数据库操作
●创建数据库、数据表,并向表中插入数据

[root@mysql1 ~]# mysql -uroot -p
Enter password: 
mysql> create database player;
mysql> use player;
Database changed
mysql> create table player (id int(4) not null,name varchar(10) not null,level int(3) not null,primary key (`id`));
mysql> insert into player (id,name,level) values ('30','抢宝真多呀',47);
mysql> insert into player (id,name,level) values ('15','新五皇·白胡子',46);
mysql> insert into player (id,name,level) values ('63','新五皇–敬神',46);
mysql> insert into player (id,name,level) values ('199','D 丶狙击王',46);
mysql> insert into player (id,name,level) values ('298','唐三',46);
mysql> insert into player (id,name,level) values ('51','新五皇·暴雪',45);
mysql> insert into player (id,name,level) values ('272','D 丶抢人头辅助',45);

●升序、降序查询

mysql> select id,name,level from player where level>=45 order by level desc;
'//查询45级以上的用户,以level降序'
+-----+----------------------+-------+
| id  | name                 | level |
+-----+----------------------+-------+
|  30 | 抢宝真多呀           |    47 |
|  15 | 新五皇·白胡子        |    46 |
|  63 | 新五皇–敬神          |    46 |
| 199 | D 丶狙击王           |    46 |
| 298 | 唐三                 |    46 |
|  51 | 新五皇·暴雪          |    45 |
| 272 | D 丶抢人头辅助       |    45 |
+-----+----------------------+-------+
7 rows in set (0.00 sec)

mysql> select id,name,level from player where level>=45 order by level desc,id desc;
'//查询45级以上的用户,以level降序和id降序排列'
+-----+----------------------+-------+
| id  | name                 | level |
+-----+----------------------+-------+
|  30 | 抢宝真多呀           |    47 |
| 298 | 唐三                 |    46 |
| 199 | D 丶狙击王           |    46 |
|  63 | 新五皇–敬神          |    46 |
|  15 | 新五皇·白胡子        |    46 |
| 272 | D 丶抢人头辅助       |    45 |
|  51 | 新五皇·暴雪          |    45 |
+-----+----------------------+-------+
7 rows in set (0.00 sec)

1.1.2 对结果进行分组

■使用GROUP BY语句来实现分组
■通常结合聚合函数一起使用
■可以按一个或多个字段对结果进行分组

■GROUP BY的语法结构
●SELECT column_name,aggregate_function(column_name)FROM table_name WHERE column_name operator value GROUP BY column_name;

mysql> select count(name),level from player where level>=45 group by level;
'//查询45级以上的用户,以等级为分组,每个等级有多少人'
+-------------+-------+
| count(name) | level |
+-------------+-------+
|           2 |    45 |
|           4 |    46 |
|           1 |    47 |
+-------------+-------+
3 rows in set (0.00 sec)

mysql> select count(name),level from player where level >=45 group by level order by count(name) desc;
'//查询45级以上,以等级为分组,将每个等级有的人数按降序排序'
+-------------+-------+
| count(name) | level |
+-------------+-------+
|           4 |    46 |
|           2 |    45 |
|           1 |    47 |
+-------------+-------+
3 rows in set (0.00 sec)

1.1.3 限制结果条目

■只返回SELECT查询结果的第一行或前几行
■使用LIMIT语句限制条目

■LIMIT 的第一个参数是位置偏移量(可选参数),是设置 MySQL 从哪一行开始显示。
■如果不设定第一个参数,将会从表中的第一条记录开始显示。
■第一条记录的位置偏移量是 0,第二条是 1。
■减少了数据结果的返回时间,提高了执行效率,也解决了由于数据量过大从而导致的性能问题。

■LIMIT语法结构
●SELECT column1,column2,… FROM table_name LIMIT [offset,] number;

■向player表中插入新数据

mysql> insert into player (id,name,level) values ('1','修欧拉卡',10);
mysql> insert into player (id,name,level) values ('2','起风了',10);
mysql> insert into player (id,name,level) values ('3','吊打低V',15);
mysql> insert into player (id,name,level) values ('4','小花',14);
mysql> insert into player (id,name,level) values ('5','小舞',35);
mysql> select id,name,level from player limit 3;
'//查询前三行记录'
+----+--------------+-------+
| id | name         | level |
+----+--------------+-------+
|  1 | 修欧拉卡     |    10 |
|  2 | 起风了       |    10 |
|  3 | 吊打低V      |    15 |
+----+--------------+-------+
3 rows in set (0.00 sec)

mysql> select id,name,level from player order by level desc limit 3;
'//查询记录按等级level降序排列,只取前三行记录'
+----+----------------------+-------+
| id | name                 | level |
+----+----------------------+-------+
| 30 | 抢宝真多呀           |    47 |
| 15 | 新五皇·白胡子        |    46 |
| 63 | 新五皇–敬神          |    46 |
+----+----------------------+-------+
3 rows in set (0.01 sec)

mysql> select id,name,level from player limit 2,3;
'//从第三条记录开始显示之后的3条数据'
+----+------------+-------+
| id | name       | level |
+----+------------+-------+
|  3 | 吊打低V    |    15 |
|  4 | 小花       |    14 |
|  5 | 小舞       |    35 |
+----+------------+-------+
3 rows in set (0.00 sec)
+----+------------+-------+
| id | name       | level |
+----+------------+-------+
|  3 | 吊打低V    |    15 |
|  4 | 小花       |    14 |
|  5 | 小舞       |    35 |
+----+------------+-------+
3 rows in set (0.00 sec)

1.1.4 设置别名

■使用AS语句设置别名,关键字AS可省略
■设置别名时,保证不能与库中其他表或字段名称冲突

■别名的语法结构
●SELECT column_name AS alias_name FROM table_name;
●SELECT column_name(s) FROM table_name AS alias_name;

mysql> select count(*) as number from player;
'//统计表内所有记录共有多少条'
+--------+
| number |
+--------+
|     12 |
+--------+
1 row in set (0.01 sec)

mysql> select p.id,p.name from player as p limit 3;
'//将player表的别名设置为p'
+----+--------------+
| id | name         |
+----+--------------+
|  1 | 修欧拉卡     |
|  2 | 起风了       |
|  3 | 吊打低V      |
+----+--------------+
3 rows in set (0.00 sec)

mysql> create table tmp as select * from player;
'//创建表tmp时将player表内的数据写入tmp表,去掉as效果一样'
Query OK, 12 rows affected (0.01 sec)
Records: 12  Duplicates: 0  Warnings: 0

mysql> select count(*) from tmp;
+----------+
| count(*) |
+----------+
|       12 |
+----------+
1 row in set (0.00 sec)

1.1.5 通配符

■用于替换字符串中的部分字符
■通常配合LIKE一起使用,并协同WHERE完成查询

■常用通配符
●%:表示零个、一个或多个
●_表示单个字符

■插入新数据

mysql> insert into player (id,name,level) values ('238','sagou 轰总',7);
mysql> insert into player (id,name,level) values ('795','senoku',15);
mysql> insert into player (id,name,level) values ('2460','shirley',1);
mysql> insert into player (id,name,level) values ('448','useless',1);
mysql> insert into player (id,name,level) values ('713','guess',25);
mysql> insert into player (id,name,level) values ('1979','Theshy',24);
mysql> insert into player (id,name,level) values ('2237','leslieF',3);
mysql> insert into player (id,name,level) values ('1735','oooooo',1);
mysql> insert into player (id,name,level) values ('2718','ooo',1);

mysql> select id,name,level from player where name like 's%';
'//name 字段以 s 开头的记录'
+------+--------------+-------+
| id   | name         | level |
+------+--------------+-------+
|  238 | sagou 轰总   |     7 |
|  795 | senoku       |    15 |
| 2460 | shirley      |     1 |
+------+--------------+-------+
3 rows in set (0.00 sec)

mysql> select id,name,level from player where name like '%s';
'//name 字段以 s 结尾的记录'
+-----+---------+-------+
| id  | name    | level |
+-----+---------+-------+
| 448 | useless |     1 |
| 713 | guess   |    25 |
+-----+---------+-------+
2 rows in set (0.00 sec)

mysql> select id,name,level from player where name like '%es%';
'//name 字段中间含 es 的记录'
+------+---------+-------+
| id   | name    | level |
+------+---------+-------+
|  448 | useless |     1 |
|  713 | guess   |    25 |
| 1979 | Theshy  |    24 |
| 2237 | leslieF |     3 |
+------+---------+-------+
4 rows in set (0.00 sec)

'//如果匹配name字段中某一个字符,可以使用%。但是MySQL提供的专门针对单个字符的通配符,就是“_”一个下划线,
使用单个下划线可以替换字符串中的某个单字符'

mysql> select id,name,level from player where name like '_uess';
'//替换开头的一个字符'
+-----+-------+-------+
| id  | name  | level |
+-----+-------+-------+
| 713 | guess |    25 |
+-----+-------+-------+
1 row in set (0.00 sec)

mysql> select id,name,level from player where name like 'use____';
'//替换结尾的四个字符'
+-----+---------+-------+
| id  | name    | level |
+-----+---------+-------+
| 448 | useless |     1 |
+-----+---------+-------+
1 row in set (0.00 sec)

mysql> select id,name,level from player where name like 'shi_ley';
'//替换中间的一个字符'
+------+---------+-------+
| id   | name    | level |
+------+---------+-------+
| 2460 | shirley |     1 |
+------+---------+-------+
1 row in set (0.00 sec)

'//通配符“%”和“_”不仅可以单独使用,也可以组合使用'

mysql> select id,name,level from player where name like '_es%';
'//name 字段中,开头有一个字符,
接着是es两个字符,后面再跟着零个、一个或多个字符,从player表中查询这样的数据'
+------+---------+-------+
| id   | name    | level |
+------+---------+-------+
| 2237 | leslieF |     3 |
+------+---------+-------+
1 row in set (0.00 sec)

1.1.6 子查询

■也被称作内查询或者嵌套查询,是指在一个查询语句里面还嵌套着另一个查询■语句子查询语句是先于主查询语句被执行的。
■其结果作为外层的条件返回给主查询进行下一步的查询过滤。
■子查询不仅可以在 SELECT 语句中使用,在 INERT、UPDATE、DELETE
中也同样适用。
■可以多层嵌套。

■IN 的语法结构如下
●<表达式> [NOT] IN <子查询>

mysql> select name,level from player where id in(select id from player where level>=45);
'//先查出等级大于等于45级的 ID,然后在判断player表内的ID是不是在这个结果集内,如果在就打印此行的名字和等级。'
+----------------------+-------+
| name                 | level |
+----------------------+-------+
| 新五皇·白胡子        |    46 |
| 抢宝真多呀           |    47 |
| 新五皇·暴雪          |    45 |
| 新五皇–敬神          |    46 |
| D 丶狙击王           |    46 |
| D 丶抢人头辅助       |    45 |
| 唐三                 |    46 |
+----------------------+-------+
7 rows in set (0.00 sec)

'//子查询是被放到括号内的,这个括号是无法省略的,缺失则会报错,无法形成子查询。'

'//子查询还可以用在 INSERT 语句中。子查询的结果集可以通过 INSERT 语句插入到其他的表中。'

'//先清空之前使用的 tmp 表,然后通过子查询的方式将 player 的内容插入到 tmp 表中'

mysql> truncate table tmp;		
'//清空tmp表'
Query OK, 0 rows affected (0.01 sec)

mysql> insert into tmp select * from player where id in (select id from player); 
'//将player表的内容插入tmp 表'
Query OK, 21 rows affected (0.00 sec)
Records: 21  Duplicates: 0  Warnings: 0

mysql> insert into tmp select * from player;
'//可跟上面子查询 SQL 达到同样的效果'
Query OK, 21 rows affected (0.00 sec)
Records: 21  Duplicates: 0  Warnings: 0

'//update语句也可以使用子查询。update内的子查询,在set更新内容时,可以是单独的一列,也可以是多列。'

'//执行以下操作即可通过子查询实现将等级大于等于 47 的用户减去 7'
mysql> select id,name,level from tmp where id=30;
'//ID 是 30 的用户等级是 47 级,最大级别'
+----+-----------------+-------+
| id | name            | level |
+----+-----------------+-------+
| 30 | 抢宝真多呀      |    47 |
+----+-----------------+-------+
1 row in set (0.00 sec)

mysql> update tmp set level = level - 7 where id in (select id from tmp where level >= 47);
ERROR 1093 (HY000): You can't specify target table 'tmp' for update in FROM clause
''//类似 select 方式的子查询,MySQL 不支持,需要多引入一层子查询'
mysql> update tmp set level = level - 7 where id in (select a.id from (select id from tmp where level >= 47) a);
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select id,name,level from tmp where id=30;
+----+-----------------+-------+
| id | name            | level |
+----+-----------------+-------+
| 30 | 抢宝真多呀      |    40 |
+----+-----------------+-------+
1 row in set (0.00 sec)
'//可以看到等级已经少了 7 级'

'//DELETE也适用于子查询。例如,先将原来47级的用户等级恢复,然后通过子查询的方式将47级用户删除,实现方式类似 UPDATE 的子查询'
mysql> update tmp set level=47 where id=30;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> delete from tmp where id in (select a.id from (select id from tmp where level=47) a);
Query OK, 1 row affected (0.01 sec)
mysql>select id,name,level from tmp where id=30;	
'//等级为 47 的用户已经被删除'
Empty set (0.00 sec)

'//在IN前面还可以添加NOT,其作用与IN相反,表示否定(即不在子查询的结果集里面)'
mysql> select name,level from tmp where id not in (select id from tmp where level < 45); 
'//查询用户等级不小于 45 级的用户'
+----------------------+-------+
| name                 | level |
+----------------------+-------+
| 新五皇·白胡子        |    46 |
| 新五皇·暴雪          |    45 |
| 新五皇–敬神          |    46 |
| D 丶狙击王           |    46 |
| D 丶抢人头辅助       |    45 |
| 唐三                 |    46 |
+----------------------+-------+
6 rows in set (0.01 sec)

'//子查询上也可以使用比较运算符(=、<、>、>=、<=),这些运算符主要是对运算符前面的表达式和后面的子查询进行比较运算'
mysql> select id,name,level from tmp where id = (select id from tmp where name='shirley');
'//查询出名字是 shirley 的记录,并输出其 ID、名字和等级信息'
+------+---------+-------+
| id   | name    | level |
+------+---------+-------+
| 2460 | shirley |     1 |
+------+---------+-------+
1 row in set (0.00 sec)

'//EXIST 这个关键字在子查询时,主要用于判断子查询的结果集是否为空。如果不为空, 则返回 TRUE;反之,则返回FALSE'
mysql> select count(*) as number from tmp where EXISTS (select id from tmp where name='shirley'); 
'//先通过子查询判断返回是否为TRUE,如果用户shirley存在,则计算整个tmp表的总记录数量'
+--------+
| number |
+--------+
|     18 |
+--------+
1 row in set (0.00 sec)

1.2 NULL值

■NULL来表示缺失的值,也就是在表中该字段是没有值的。
■如果在创建表时,限制某些字段不为空,则可以使用NOT NULL关键字,不使用则默认可以为空。
■在向表内插入记录或者更新记录时,如果该字段没有NOT NULL并且没有值,这时候新记录的该字段将被保存为 NULL。
■NULL 值与数字 0 或者空白(spaces)的字段是不同的,值为NULL的字段是没有值的。
■在SQL语句中,使用IS NULL可以判断表内的某个字段是不是NULL值,相反的用IS NOT NULL 可以判断不是NULL值。
■空值就是在表的字段中存储空字符(‘’)
■空值的长度为 0,不占用空间的;而NULL值的长度是 NULL,是占用空间的。
■IS NULL 或者 IS NOT NULL,是用来判断字段是不是为 NULL 或者不是 NULL,不能查出是不是空值的。空值的判断使用=’’或者<>’’来处理。
■在通过 count()计算有多少记录数时,如果遇到 NULL 值会自动忽略掉,遇到空值会加入到记录中进行计算。

‘'//创建一个表test,该表包含不设置NOT NULL的字段,然后向表中插入不同的记录值,其中包括NULL值和实际有值的记录,最后通过 SELECT 查询字段中包括 NULL 和不包括 NULL 的记录值'
mysql> CREATE TABLE `test` (
    -> `id` int(10) NOT NULL AUTO_INCREMENT,
    -> `NAME` varchar(32) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
    -> `level` int(10) NOT NULL,
    -> `coin` int(32),
    ->  PRIMARY KEY (id)
    -> ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.01 sec)

mysql> insert into test(name,level) values('aa',10);		
'//插入的记录中不包括 coin 字段'
Query OK, 1 row affected (0.01 sec)

mysql>insert into test(name,level,coin) values('ab',20,100);		###插入的记录中包括 coin 字段
Query OK, 1 row affected (0.00 sec)

mysql>select * from test where coin is null;		
'//查询 coin 字段为空值的记录'
+----+------+-------+------+
| id | NAME | level | coin |
+----+------+-------+------+
|    1 | aa	|	10 | NULL |
+----+------+-------+------+
1 row in set (0.00 sec)

mysql> select * from test where coin is not null;		
'//查询coin 字段不为空的记录'
+----+------+-------+------+
| id | NAME | level | coin |
+----+------+-------+------+

|    2 | ab	|	20 | 100 |
+----+------+-------+------+
1 row in set (0.00 sec)

1.3 正则表达式

■MySQL 的正则表达式使用 REGEXP 这个关键字来指定正则表达式的匹配模式
■REGEXP 操作符所支持的匹配模式

^ :匹配文本的开始字符——‘^bd’: 匹配以 bd 开头的字符串
$ :匹配文本的结束字符——‘qn$’: 匹配以 qn 结尾的字符串
.:匹配任何单个字符——‘s.t’ :匹配任何s 和t 之间有一个字符的字符串
:匹配零个或多个在它前面的字符——‘fot’ :匹配 t 前面有任意个 o
+:匹配前面的字符 1 次或多次——‘hom+’ :匹配以 ho 开头,后面至少一个m 的字符串字符串
‘clo’ :匹配含有 clo 的字符串
p1|p2:匹配 p1 或 p2——‘bg|fg’ :匹配 bg 或者 fg
[…]:匹配字符集合中的任意一个字符——‘[abc]’ :匹配 a 或者 b 或者 c
[^…] :匹配不在括号中的任何字符——‘[^ab]’: 匹配不包含 a 或者 b 的字符串
{n}:匹配前面的字符串 n 次——‘g{2}’ :匹配含有 2 个 g 的字符串
{n,m}:匹配前面的字符串至少 n 次,至多m 次——‘f{1,3}’: 匹配 f 最少 1 次,最多 3 次

★方括号“[]”指定了一个字符集合,只匹配其中的一个字符。“”不仅可以放到左侧,也可以放到方括号内,放到左侧表示以这些字符集内的字符开头,而放到方括号内则表示不在指定的字符集合内的字符。例如“[d-f]”表示除 d、e、f 以外的任何字符。

1.3.1 以特定字符串开头的记录

mysql> select id,name,level from player where name REGEXP '^us';
'//在player表中查询以us开头的name字段并打印对应的id、name 和 level 记录'
+-----+---------+-------+
| id  | name    | level |
+-----+---------+-------+
| 448 | useless |     1 |
+-----+---------+-------+
1 row in set (0.00 sec)

1.3.2 以特定字符串结尾的记录

mysql> select id,name,level from player where name REGEXP 'ss$';
'//在 player 表中查询以 ss 结尾的 name 字段并打印对应的 id、name 和 level 记录'
+-----+---------+-------+
| id  | name    | level |
+-----+---------+-------+
| 448 | useless |     1 |
| 713 | guess   |    25 |
+-----+---------+-------+
2 rows in set (0.00 sec)

1.3.3 包含指定字符串的记录

mysql> select id,name,level from player where name REGEXP 'ok';
'//在player表中查询包含ok字符串的name字段并打印对应的 id、name 和 level
记录'
+-----+--------+-------+
| id  | name   | level |
+-----+--------+-------+
| 795 | senoku |    15 |
+-----+--------+-------+
1 row in set (0.00 sec)

1.3.4 以“.”代替字符串中的任意一个字符的记录

mysql> select id,name,level from player where name REGEXP 'shir.ey';
'//在player表中查询包含字符串shir 与 ey,且两个字符串之间只有一个字符的name 字段并打印对应的 id、name 和 level 记录'
+------+---------+-------+
| id   | name    | level |
+------+---------+-------+
| 2460 | shirley |     1 |
+------+---------+-------+
1 row in set (0.00 sec)

1.3.5 匹配包含或者关系的记录

mysql> select id,name,level from player where name REGEXP 'ok|ss';
'//在 player 表中查询包含字符串ok或者ss的name字段并打印对应的 id、name
和 level 记录'
+-----+---------+-------+
| id  | name    | level |
+-----+---------+-------+
| 448 | useless |     1 |
| 713 | guess   |    25 |
| 795 | senoku  |    15 |
+-----+---------+-------+
3 rows in set (0.00 sec)

1.3.6 “*”匹配前面字符的任意多次

mysql> select id,name,level from player where name REGEXP 'oooo*';
'//在 player 表中查询包含三个或者更多个连续的 o 的 name 字段并打印对应的 id、name 和 level 记录'
+------+--------+-------+
| id   | name   | level |
+------+--------+-------+
| 1735 | oooooo |     1 |
| 2718 | ooo    |     1 |
+------+--------+-------+
2 rows in set (0.00 sec)

1.3.7 “+”匹配前面字符至少一次

mysql> select id,name,level from player where name REGEXP 'oooo+';
'//在player表中查询包含四个或者更多个o的 name 字段并打印对应的 id、name
和 level 记录'
+------+--------+-------+
| id   | name   | level |
+------+--------+-------+
| 1735 | oooooo |     1 |
+------+--------+-------+
1 row in set (0.00 sec)

1.3.8 匹配指定字符集中的任意一个

mysql> select id,name,level from player where name REGEXP '^[d-f]';
'//在 player 表中查询包含以 d、e、f 开头的 name 字段并打印对应的 id、name 和level 记录'
+-----+----------------------+-------+
| id  | name                 | level |
+-----+----------------------+-------+
| 199 | D 丶狙击王           |    46 |
| 272 | D 丶抢人头辅助       |    45 |
+-----+----------------------+-------+
2 rows in set (0.00 sec)

1.4 运算符

■用于对记录中的字段值进行运算.
■算术运算符、比较运算符、逻辑运算符和位运算符

1.4.1 算术运算符

+:加法
-:减法
*:乘法
/:除法
%:取余数

■在除法运算和求余数运算中,除数不能为 0,若除数是 0,返回的结果则为 NULL
■如果有多个运算符,按照先乘除后加减的优先级进行运算,相同优先级的运算 符没有先后顺序
■某些字符串类型的字段存储的数字型字符串,这些字段在进行算术运算时将会被自动转换为数字的值
■如果字符串的开始部分是数字,在转换时将被转换为这个数字;如果是既包含字符又包含数字得的混合字符串,无法转换为数字时,将被转换为 0

mysql> select 1+3 as addition, 5-1 as subtraction, 5*3 as multiplication, 8/2 as division, 15%2 as remainder;
+----------+-------------+----------------+----------+-----------+
| addition | subtraction | multiplication | division | remainder |
+----------+-------------+----------------+----------+-----------+
|        4 |           4 |             15 |   4.0000 |         1 |
+----------+-------------+----------------+----------+-----------+
1 row in set (0.00 sec)

1.4.2 比较运算符

■是查询数据记录时经常使用的一类运算符
■通过使用比较运算符可以判断出表中有哪些记录是符合条件的,如果比较的结果为真则返回 1,如果为假则返回 0,比较的结果如果不确定则返回 NULL
■字符串在进行比较的时候默认是不区分大小写的,如果要区分大小写可以通过 binary 关键字来实现

■常用的比较运算符
=:等于
IS NOT NULL:判断一个值是否不为 NULL
>:大于
BETWEEN AND:两者之间
<:小于
IN:在集合中
>=:大于等于
LIKE:通配符匹配
<=:小于等于
GREATEST:两个或多个参数时返回最大值
!=或<>:不等于
LEAST:两个或多个参数时返回最小值
IS NULL:判断一个值是否为
NULL REGEXP:正则表达式

■等于运算符
●用来判断数字、字符串和表达式是否相等的,如果相等则返回1,如果不相等则返回0
●如果比较的两者有一个值是 NULL,则比较的结果就是 NULL
●字符的比较是根据 ASCII 码来判断的.如果 ASCII 码相等,则表示两个字符相同;如果ASCII码不相等,则表示两个字符不相同

■如果两者都是整数,则按照整数值进行比较。
■如果一个整数一个字符串,则会自动将字符串转换为数字,再进行比较。
■如果两者都是字符串,则按照字符串进行比较。
■如果两者中至少有一个值是 NULL,则比较的结果是 NULL。

mysql> select 2=5,2='2','e'='e',(2+5)=(3+4),'r'=NULL;
+-----+-------+---------+-------------+----------+
| 2=5 | 2='2' | 'e'='e' | (2+5)=(3+4) | 'r'=NULL |
+-----+-------+---------+-------------+----------+
|   0 |     1 |       1 |           1 |     NULL |
+-----+-------+---------+-------------+----------+
1 row in set (0.00 sec)

■不等于运算符
●不等于号有两种写法,分别是<>或者!=,用于针对数字、字符串和表达式不相等的比较
●如果不相等则返回 1,如果相等则返回 0,正好跟等于的返回值相反。不等于运算符不能用于判断 NULL

mysql> SELECT 'kgc'<>'bdqn', 1<>2, 3!=3, 2.5!=2, NULL<>NULL ;
+---------------+------+------+--------+------------+
| 'kgc'<>'bdqn' | 1<>2 | 3!=3 | 2.5!=2 | NULL<>NULL |
+---------------+------+------+--------+------------+
|             1 |    1 |    0 |      1 |       NULL |
+---------------+------+------+--------+------------+
1 row in set (0.00 sec)

■大于、大于等于、小于、小于等于运算符
●大于(>)运算符用来判断左侧的操作数是否大于右侧的操作数,若大于返回 1,否则返回 0,同样不能用于判断 NULL。
●小于(<)运算符用来判断左侧的操作数是否小于右侧的操作数,若小于返回 1,否则返回 0,同样不能用于判断 NULL。
●大于等于(>=)判断左侧的操作数是否大于等于右侧的操作数,若大于等于返回 1,否则返回 0,不能用于判断 NULL。
●小于等于(<=)判断左侧的操作数是否小于等于右侧的操作数,若小于等于返回 1,否则返回 0,不能用于判断 NULL。

mysql> select 5>4,'a'>'b',2>=3,(2+3)>=(1+2),4.4<3,1<2,'x'<='y',5<=5.5,'u'>=NULL;
+-----+---------+------+--------------+-------+-----+----------+--------+-----------+
| 5>4 | 'a'>'b' | 2>=3 | (2+3)>=(1+2) | 4.4<3 | 1<2 | 'x'<='y' | 5<=5.5 | 'u'>=NULL |
+-----+---------+------+--------------+-------+-----+----------+--------+-----------+
|   1 |       0 |    0 |            1 |     0 |   1 |        1 |      1 |      NULL |
+-----+---------+------+--------------+-------+-----+----------+--------+-----------+
1 row in set (0.00 sec)

■IS NULL、IS NOT NULL
●IS NULL 判断一个值是否为 NULL,如果为 NULL 返回 1,否则返回 0。
●IS NOT NULL 判断一个值是否不为 NULL,如果不为 NULL 返回 1,否则返回 0。例如,关于数字、字符和 NULL 值的运用
■IS NULL 和 IS NOT NULL 一个判断为空,另一个判断不为空,只是有无 NOT 这个关键字的区别,同时返回值不同

mysql> select 2 IS NULL,'f' IS NOT NULL,NULL IS NULL;
+-----------+-----------------+--------------+
| 2 IS NULL | 'f' IS NOT NULL | NULL IS NULL |
+-----------+-----------------+--------------+
|         0 |               1 |            1 |
+-----------+-----------------+--------------+
1 row in set (0.00 sec)

■BETWEEN AND
●用于判断一个值是否落在某两个值之间。
●判断某数字是否在另外两个数字之间,也可以判断某英文字母是否在另外两个字母之间

mysql> select 4 BETWEEN 2 AND 6,5 BETWEEN 6 AND 8,'c' BETWEEN 'a' AND 'f';
+-------------------+-------------------+-------------------------+
| 4 BETWEEN 2 AND 6 | 5 BETWEEN 6 AND 8 | 'c' BETWEEN 'a' AND 'f' |
+-------------------+-------------------+-------------------------+
|                 1 |                 0 |                       1 |
+-------------------+-------------------+-------------------------+
1 row in set (0.00 sec)

■LEAST、GREATEST
●LEAST:当有两个或者多个参数时,返回其中的最小值。如果其中一个值为 NULL,则返回结果就为 NULL。
●GREATEST:当有两个或者多个参数时,返回其中的最大值。如果其中一个值为 NULL, 则返回结果就为 NULL

'//判断一组数字或字母中哪个最小、哪个最大,可以通过使用 LEAST 和
GREATEST 来实现'
mysql> SELECT least(1,2,3),least('a','b','c'),greatest(1,2,3),greatest('a','b','c');
+--------------+--------------------+-----------------+-----------------------+
| least(1,2,3) | least('a','b','c') | greatest(1,2,3) | greatest('a','b','c') |
+--------------+--------------------+-----------------+-----------------------+
|            1 | a                  |               3 | c                     |
+--------------+--------------------+-----------------+-----------------------+
1 row in set (0.00 sec)
'//LEAST 比较的参数为数字时,返回的是其中最小的值;当比较的参数为字符串时,
返回字母表中顺序最靠前的字符。GREATEST 比较的参数为数字时, 返回的是其中最大的值;当比较的参数为字符串时,返回字母表中顺序最靠后的字符'

■IN、NOT IN
●IN 判断一个值是否在对应的列表中,如果是返回 1,否则返回 0。
●NOT IN 判断一个值是否不在对应的列表中,如果不是返回 1,否则返回 0。

'//判断某数字是否在一组数字中,也可判断某字符是否在一组字符中'
mysql> SELECT 2 in (1,2,3,4,5),'c' not in ('a','b','c');
+------------------+--------------------------+
| 2 in (1,2,3,4,5) | 'c' not in ('a','b','c') |
+------------------+--------------------------+
|                1 |                        0 |
+------------------+--------------------------+
1 row in set (0.00 sec)

■LIKE、NOT LIKE
●LIKE 用来匹配字符串,如果匹配成功则返回 1,反之返回 0。LIKE 支持两种通配符:’%’ 用于匹配任意数目的字符,而’_’只能匹配一个字符。NOT LIKE 正好跟 LIKE 相反,如果没有匹配成功则返回 1,反之返回 0。

'//判断某字符串能否匹配成功,分单字符匹配和多字符匹配,也可以判断不匹配'
mysql> SELECT 'bdqn' LIKE 'bdq_','kgc' LIKE '%c','etc' NOT LIKE '%th';
+--------------------+-----------------+----------------------+
| 'bdqn' LIKE 'bdq_' | 'kgc' LIKE '%c' | 'etc' NOT LIKE '%th' |
+--------------------+-----------------+----------------------+
|                  1 |               1 |                    1 |
+--------------------+-----------------+----------------------+
1 row in set (0.00 sec)

1.4.3 逻辑运算符

■又被称为布尔运算符,通常用来判断表达式的真假,如果为真返回 1,否则返回 0,真和假也可以用 TRUE 和 FALSE 表示
NOT 或 ! 逻辑非
AND 或 && 逻辑与
OR 或 || 逻辑或
XOR 逻辑异或

■逻辑非
●逻辑运算符中最简单的运算符就是逻辑非,逻辑非使用 NOT 或!表示
●逻辑非将跟在它后面的逻辑测试取反,把真变为假,把假变为真
●如果 NOT 后面的操作数为 0 时,所得值为 1;如果操作数为非 0 时,所得值为 0;如果操作数为 NULL 时,所得值为 NULL

'//对非 0 值和 0 值分别作逻辑非运算'
mysql>SELECT not 2,!3,not 0,!(4-4);
+-------+----+-------+--------+
| not 2 | !3 | not 0 | !(4-4) |
+-------+----+-------+--------+
|	0 |   0 |	1 |	1 |
+-------+----+-------+--------+
1 row in set (0.00 sec)

■逻辑与
●逻辑与通常用于判断两个值或多个值的有效性
●如果所有值都是真返回 1,否则返回 0
●逻辑与使用 AND 或者&&表示

'//对非 0 值、0 值和 NULL 值分别作逻辑与运算'
mysql> SELECT 2 AND 3,4 && 0,0 && NULL,1 AND NULL;
+---------+--------+-----------+------------+
| 2 AND 3 | 4 && 0 | 0 && NULL | 1 AND NULL |
+---------+--------+-----------+------------+
|       1 |      0 |         0 |       NULL |
+---------+--------+-----------+------------+
1 row in set (0.00 sec)

■逻辑或
●逻辑或表示包含的操作数,任意一个为非零值并且不是 NULL 值时,返回 1,否则返回0
●逻辑或通常使用 OR 或者||来表示

'//对非 0 值、0 值和 NULL 值分别作逻辑或运算'
mysql> SELECT 2 OR 3,4 or 0,0 OR NULL,1 or NULL;
+--------+--------+-----------+-----------+
| 2 OR 3 | 4 or 0 | 0 OR NULL | 1 or NULL |
+--------+--------+-----------+-----------+
|      1 |      1 |      NULL |         1 |
+--------+--------+-----------+-----------+
1 row in set (0.00 sec)

■逻辑异或
●两个非 NULL 值的操作数,如果两者都是 0 或者都是非 0,则返回 0;如果一个为 0, 另一个为非 0,则返回结果为 1;
●当任意一个值为 NULL 时,返回值为 NULL。

'//对非0 值、0 值和 NULL 值分别作逻辑异或运算'
mysql>SELECT 2 XOR 3,0 XOR 0,0 XOR 5,1 XOR NULL,NULL XOR NULL;
+---------+---------+---------+------------+---------------+
| 2 XOR 3 | 0 XOR 0 | 0 XOR 5 | 1 XOR NULL | NULL XOR NULL |
+---------+---------+---------+------------+---------------+
|	0 |	0 |	1 |	NULL |	NULL |
+---------+---------+---------+------------+---------------+
1 row in set (0.00 sec)

■位运算符
●对二进制数进行计算的运算符
●先将操作数变成二进制格式,然后进行位运算,最后在将计算结果从二进制变回到十进制格式,方便用户查看
& :按位与
| :按位或
~ :按位取反
^ :按位异或
<< :按位左移
>> :按位右移

'//对数字进行按位与、或和取反运算'
mysql> SELECT 10 & 15, 10 | 15, 10 ^ 15, 5 &~1;
+---------+---------+---------+-------+
| 10 & 15 | 10 | 15 | 10 ^ 15 | 5 &~1 |
+---------+---------+---------+-------+
|      10 |      15 |       5 |     4 |
+---------+---------+---------+-------+
1 row in set (0.00 sec)

注:
●10 转换为二进制数是 1010, 15 转换为二进制数是 1111。
●按位与运算(&),是对应的二进制位都是 1 的,它们的运算结果为 1,否则为 0,所以 10 & 15 的结果为 10。
●按位或运算(|),是对应的二进制位有一个或两个为 1 的,运算结果为 1,否则为 0, 所以 10 | 15 的结果为 15。
●按位异或运算(^),是对应的二进制位不相同时,运算结果 1,否则为 0,所以 10 ^ 15的结果为 5。
●按位取反(~),是对应的二进制数逐位反转,即 1 取反后变为 0, 0 取反后变为 1。数字 1 的二进制是 0001,取反后变为 1110, 数字 5 的二进制是 0101,将 1110 和 0101,进行求与操作,其结果是二进制的 0100,转换为十进制就是 4

'//对数字进行左移或右移的运算'
mysql> SELECT 1<<2, 2<<2,10>>2,15>>2;
+------+------+-------+-------+
| 1<<2 | 2<<2 | 10>>2 | 15>>2 |
+------+------+-------+-------+
|    4 |    8 |     2 |     3 |
+------+------+-------+-------+
1 row in set (0.00 sec)

■左移或右移运算符,都是将数转换为二进制后,然后在左移或右移指定的位数,超出的位数将被移除并丢弃,空出来的位置用 0 补齐。
例如,“2<<2”将数字 2 的二进制数 0010, 向左移动两位后变成 10,右侧用 00 补齐,最终变为二进制的 1000,转换为十进制是 8。
“15>>2”将数字 15 转换为二进制是 1111,向右移动两位,右侧的两位 11 被丢弃,变为 11, 左侧用 00 补齐,最终变为二进制的 0011,转换为十进制就是 3。
以上不管哪种运算符,在使用过程中都有优先级问题。运算符的优先级决定了不同的运 算符在计算过程中的先后顺序。级别高的运算符会先进行计算,如果运算符的级别相同,
MySQL 会按照顺序从左到右依次进行计算。如果不确定所使用的运算符的优先级,可以使用()改变优先级。常用的运算符优先级情况如表 5-6 所示。
“!”的优先级最高,而“:=”的优先级最低

mysql中除法并保留两位小数 sql除法运算保留两位_mysql

1.5 连接查询

■将来自两个或多个表的行结合起来,基于这些表之间的共同字段,进行数据的拼接
●内连接、左连接和右连接

1.5.1 创建表

CREATE TABLE `a_player` (
`a_id` int(11) DEFAULT NULL,
`a_name` varchar(32) DEFAULT NULL,
`a_level` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `b_player` (
`b_id` int(11) DEFAULT NULL,
`b_name` varchar(32) DEFAULT NULL,
`b_level` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

1.5.2 插入数据

insert into a_player(a_id, a_name, a_level) values(1, 'aaaa', 10); insert into a_player(a_id, a_name, a_level) values(2, 'bbbb', 20); insert into a_player(a_id, a_name, a_level) values(3, 'cccc', 30); insert into a_player(a_id, a_name, a_level) values(4, 'dddd', 40);

insert into b_player(b_id, b_name, b_level) values(2, 'bbbb', 20); insert into b_player(b_id, b_name, b_level) values(3, 'cccc', 30); insert into b_player(b_id, b_name, b_level) values(5, 'eeee', 50); insert into b_player(b_id, b_name, b_level) values(6, 'ffff', 60);

1.5.3 内连接

■两张或多张表中同时符合某种条件的数据记录的组合
■通常在FROM 子句中使用关键字 INNER JOIN 来连接多张表,并使用 ON 子句设置连接条件

■系统默认的表连接,在 FROM 子句后可以省略 INNER 关键字,只使用关键字 JOIN
■同时有多个表时,也可以连续使用 INNER JOIN 来实现多表的内连接
■为了更好的性能,建议最好不要超过三个表

■内连接的语法格式
●SELECT column_name(s)FROM table1 INNER JOIN table2 ON table1.column_name = table2.column_name;

mysql>select a_id,a_name,a_level from a_player inner join b_player on a_id=b_id;
+------+--------+---------+
| a_id | a_name | a_level |
+------+--------+---------+
|	2 | bbbb	|	20 |
|	3 | cccc	|	30 |
+------+--------+---------+
2rows in set (0.00 sec)
'//将 a_player 表的每一行与 b_player 表的每一行进行比较,以检查它们是否都满足条件。当满足条件时,INNER JOIN 将返回由 a_player 表和 b_player 表中的列组成的新行。如果没有匹配项,查询将返回一个空的结果集。INNER JOIN 结果集中的行必须出现在两个表 a_player 和 b_player 中,是这两个表的交叉部分,具体的 INNER JOIN 工作原理'

1.5.4 左连接

■属于外连接的一种,外连接还包括右连接
■左连接也可以被称为左外连接,在 FROM 子句中使用 LEFT JOIN 或者 LEFT OUTER JOIN 关键字来表示
■左连接以左侧表为基础表,接收左表的所有行,并用这些行与右侧参考表中的记录进行匹配,也就是说匹配左表中的所有行以及右表中符合条件的行

mysql> select * from a_player a left join b_player b on a.a_id=b.b_id;
+------+--------+---------+------+--------+---------+
| a_id | a_name | a_level | b_id | b_name | b_level |
+------+--------+---------+------+--------+---------+
|    2 | bbbb   |      20 |    2 | bbbb   |      20 |
|    3 | cccc   |      30 |    3 | cccc   |      30 |
|    1 | aaaa   |      10 | NULL | NULL   |    NULL |
|    4 | dddd   |      40 | NULL | NULL   |    NULL |
+------+--------+---------+------+--------+---------+
4 rows in set (0.00 sec)
'//a_player 和 b_player 表中,查询出 a_player 表中所有内容,并且查询出通过 a_id 和 b_id 相等判断出的 b_player 中的部分.除了匹配的行,a_id 和 b_id 是 2 和 3 那两行,还包括了左表中有但右表中没有的行,如果有表没有对应值,则使用 NULL 代替。也就是说在左连接查询中,使用 NULL 值表示右表中没有找到与左表中匹配的记录。左连接中左表的记录将会全部表示出来,而右表只会显示符合搜索  条件的记录,也就是图中交叉的部分。右表记录不足的地方均为 NULL.'

1.5.5 右连接

■右连接也被称为右外连接,在 FROM 子句中使用 RIGHT JOIN 或者 RIGHT OUTER JOIN 关键字来表示
■右连接跟左连接正好相反,它是以右表为基础表,用于接收右表中的所有行,并用这些记录与左表中的行进行匹配,也就是说匹配右表中的每一行及左表中符合条件的记录

mysql> select * from a_player a right join b_player b on a.a_id=b.b_id;
+------+--------+---------+------+--------+---------+
| a_id | a_name | a_level | b_id | b_name | b_level |
+------+--------+---------+------+--------+---------+
|    2 | bbbb   |      20 |    2 | bbbb   |      20 |
|    3 | cccc   |      30 |    3 | cccc   |      30 |
| NULL | NULL   |    NULL |    5 | eeee   |      50 |
| NULL | NULL   |    NULL |    6 | ffff   |      60 |
+------+--------+---------+------+--------+---------+
4 rows in set (0.00 sec)
'//从 a_player 和 b_player 表中,查询出在 b_player 表内的所有记录,并且通过判断 a_id 和 b_id 相等,在 a_player 表内的部分.在右连接的查询结果集中,除了符合匹配规则的行外,还包括右表中有但是左表中不匹配的行,这些记录在左表中以NULL补足.'

二、 数据库函数

■MySQL 数据库函数提供了能够实现各种功能的方法,使我们在查询记录时能够更高效的输出。MySQL 内建了很多函数,常用的包括数学函数、聚合函数、字符串函数和日期时间函数。

2.1 数学函数

■数据库内存储的记录,经常要进行一系列的算术操作,所以 MySQL 支持很多数学函数

■常用的数学函数
abs(x) :返回 x 的绝对值
rand(): 返回 0 到 1 的随机数
mod(x,y):返回 x 除以 y 以后的余数
power(x,y):返回 x 的 y 次方
round(x):返回离 x 最近的整数
round(x,y):保留x 的y 位小数四舍五入后的值
sqrt(x):返回 x 的平方根
truncate(x,y):返回数字 x 截断为 y 位小数的值
ceil(x):返回大于或等于 x 的最小整数
floor(x):返回小于或等于 x 的最大整数
greatest(x1,x2…) :返回集合中最大的值
least(x1,x2…):返回集合中最小的值

■MySQL 数学函数的使用方法

mysql>select abs(-1), rand(), mod(5,3), power(2,3), round(1.89);
+---------+---------------------+----------+------------+-------------+
| abs(-1) | rand()	| mod(5,3) | power(2,3) | round(1.89) |
+---------+---------------------+----------+------------+-------------+
|	1 | 0.46176527949214474 |	2 |	8 |	2 |
+---------+---------------------+----------+------------+-------------+
1 row in set (0.00 sec)

mysql>select round(1.8937,3), truncate(1.235,2), ceil(5.2), floor(2.1), least(1.89,3,6.1,2.1);
+-----------------+-------------------+-----------+------------+-----------------------+
| round(1.8937,3) | truncate(1.235,2) | ceil(5.2) | floor(2.1) | least(1.89,3,6.1,2.1) |
+-----------------+-------------------+-----------+------------+-----------------------+
|	1.894 |	1.23 |	6 |	2 |	1.89 |
+-----------------+-------------------+-----------+------------+-----------------------+
1 row in set (0.00 sec)

2.2 聚合函数

■MySQL 数据库函数中专门有一组函数是特意为库内记录求和或者对表中的数据进行集中概括而设计的,这些函数被称作聚合函数

■常见的聚合函数
avg() :返回指定列的平均值
count() :返回指定列中非 NULL 值的个数
min() :返回指定列的最小值
max() :返回指定列的最大值
sum(x) :返回指定列的所有值之和

■MySQL 聚合函数的使用方法

mysql> select sum(level) as sum_level from player;
+-----------+
| sum_level |
+-----------+
|       483 |
+-----------+
1 row in set (0.00 sec)

mysql>select max(level) as max_level from player;
+-----------+
| max_level |
+-----------+
|	47 |
+-----------+
1 row in set (0.00 sec)

mysql>select min(level) as min_level from player;
+-----------+
| min_level |
+-----------+
|	1 |
+-----------+
1 row in set (0.00 sec)
'//聚合函数中最常用到的是 count()函数,用于统计表中的总记录数。'

2.3 字符串函数

■常用函数不仅包括数学函数和聚合函数,还包含字符串函数,MySQL 为字符串的相关操作设计了丰富的字符串函数

■常用的字符串函数
length(x) :返回字符串 x 的长度
trim() :返回去除指定格式的值
concat(x,y) :将提供的参数 x 和 y 拼接成一个字符串
upper(x) :将字符串 x 的所有字母变成大写字母
lower(x) :将字符串 x 的所有字母变成小写字母
left(x,y) :返回字符串 x 的前 y 个字符
right(x,y) :返回字符串 x 的后 y 个字符
repeat(x,y) :将字符串 x 重复 y 次
space(x) :返回 x 个空格
replace(x,y,z) :将字符串 z 替代字符串 x 中的字符串 y
strcmp(x,y) :比较 x 和 y,返回的值可以为-1,0,1
substring(x,y,z):获取从字符串 x 中的第 y 个位置开始长度为 z 的字符串
reverse(x):将字符串 x 反转

■MySQL 字符串函数的使用方法

mysql>select length('bdqn'), trim(' yellow '), concat('bd', 'qn'), upper('abc'), right('hello', 3);
+----------------+------------------+--------------------+--------------+-------------------+
| length('bdqn') | trim(' yellow ') | concat('bd', 'qn') | upper('abc') | right('hello', 3) |
+----------------+------------------+--------------------+--------------+-------------------+
|	4 | yellow	| bdqn	| ABC	| llo
|
+----------------+------------------+--------------------+--------------+-------------------+
1 row in set (0.00 sec)


mysql>select repeat('kgc', 2), replace('hello', 'll', 'kgc'), strcmp(4, 5), substring('bjbdqn', 4, 2), reverse('hello');
+------------------+-------------------------------+--------------+---------------------------+------------------+
| repeat('kgc', 2) | replace('hello', 'll', 'kgc') | strcmp(4, 5) | substring('bjbdqn', 4, 2) | reverse('hello') |
+------------------+-------------------------------+--------------+---------------------------+------------------+
| kgckgc	| hekgco	|	-1 | dq
| olleh	|
+------------------+-------------------------------+--------------+---------------------------+------------------+
1 row in set (0.00 sec)

2.4 日期时间函数

■MySQL 也支持日期时间处理,提供了很多处理日期和时间的函数

■常用的日期时间函数
curdate() :返回当前时间的年月日
curtime() :返回当前时间的时分秒
now() :返回当前时间的日期和时间
month(x) :返回日期 x 中的月份值
week(x) :返回日期 x 是年度第几个星期
hour(x) :返回 x 中的小时值
minute(x) :返回 x 中的分钟值
second(x) :返回 x 中的秒钟值
dayofweek(x) :返回 x 是星期几,1 星期日,2 星期一
dayofmonth(x) :计算日期 x 是本月的第几天
dayofyear(x) :计算日期 x 是本年的第几天

■MySQL 日期时间函数的使用方法

mysql>select curdate(),curtime(),now(),month('2020-02-09'),	week('2020-02-09'), hour('21:13:53');
+------------+-----------+---------------------+---------------------+--------------------+------------------+
| curdate()	|  curtime() | now()	| month('2020-02-09') | week('2020-02-09') | hour('21:13:53') |
+------------+-----------+---------------------+---------------------+--------------------+------------------+
| 2020-02-09 | 21:14:34    | 2020-02-09 21:14:34 |	2 |	6 |
21 |
+------------+-----------+---------------------+---------------------+--------------------+------------------+
1 row in set (0.00 sec)


mysql>select minute('21:13:53'),second('21:13:53'),	dayofweek('2020-02-09'), dayofmonth('2020-02-09'), dayofyear('2020-02-09');

+--------------------+--------------------+-------------------------+--------------------------+-------------------------+
| minute('21:13:53') | second('21:13:53') | dayofweek('2020-02-09') | dayofmonth('2020-02-09') | dayofyear('2020-02-09') |
+--------------------+--------------------+-------------------------+--------------------------+-------------------------+
|	13 |	53 |	1 |
9 |	40 |
+--------------------+--------------------+-------------------------+--------------------------+-------------------------+
1 row in set (0.00 sec)

三、存储过程

■MySQL 相关知识都是针对一个表或几个表的单条 SQL 语句,使用这样的SQL 语句虽然可以完成用户的需求,但在实际的数据库应用中,有些数据库操作可能会非常复杂,可能会需要多条 SQL 语句一起去处理才能够完成,这时候就可以使用存储过程, 轻松而高效的去完成这个需求。

3.1 存储过程简介

■MySQL 数据库存储过程是一组为了完成特定功能的 SQL 语句的集合

■存储过程这个功能是从 5.0 版本才开始支持的,它可以加快数据库的处理速度,增强数据库在实际应用中的灵活性

■存储过程在使用过程中是将常用或者复杂的工作预先使用 SQL 语句写好并用一个指定的名称存储起来,这个过程经编译和优化后存储在数据库服务器中

■当需要使用该存 储过程时,只需要调用它即可操作数据库的传统 SQL 语句在执行时需要先编译,然后再去执行,跟存储过程一对比,明显存储过程在执行上速度更快,效率更高

■存储过程在数据库中创建并保存,它不仅仅是 SQL 语句的集合,还可以加入一些特殊的控制结构,也可以控制数据的访问方式

■存储过程的应用范围很广,例如封装特定的功能、 在不同的应用程序或平台上执行相同的函数等等

■存储过程更像是面向对象方法的模拟

■存储过程的优点
■存储过程执行一次后,生成的二进制代码就驻留在缓冲区,之后如果再次调用的话,将 直接调用二进制代码,使得存储过程的执行效率和性能得到大幅提升

■存储过程是 SQL 语句加上控制语句的集合,有很强的灵活性,可以完成复杂的运算

■存储过程存储在服务器端,客户端调用时,直接在服务器端执行,客户端只是传输的调 用语句,从而可以降低网络负载。

■存储过程被创建后,可以多次重复调用,它将多条 SQL 封装到了一起,可随时针对 SQL语句进行修改,不影响调用它的客户端。

■存储过程可以完成所有的数据库操作,也可以通过编程的方式控制数据库的信息访问权限。

3.2 创建存储过程

■使用 CREATE PROCEDURE 语句创建存储过程,其语法格式:
CREATE PROCEDURE <过程名> ( [过程参数[,…] ] ) <过程体>
[过程参数[,…] ] 格式
[ IN | OUT | INOUT ] <参数名><类型>

■存储过程的名称应该尽量避免选取与 MySQL 内置的函数或者字段相同的名称,否则会发生错误。

■存储过程可以添加参数,具有自己的参数列表。参数包括参数名和其对应的类型。存在多个参数时,参数列表之间用逗号进行分隔。创建存储过程的时候可以不使用参数,但是括号要存在,也可以有一个或多个参数。

■MySQL 的参数分为:输入参数、输出参数和输入/输出参数,分别用 IN、OUT 和 INOUT 三个关键字表示。其中,输入参数可以传递给一个存储过程;输出参数用于存储过程需要返回一个操作结果的情形,而输入/输出参数既可以充当输入参数也可以充当输出参数。此外,存储过程的主体部分,被称为过程体,包含了在调用时必须执行的 SQL 语句。这个部分以关键字 BEGIN 开始,以关键字 END 结束。若过程体中只有一条 SQL 语句,则可以省略 BEGIN-END 标志。

■在存储过程的创建过程中,会用到 DELIMITER 命令。因为在 MySQL 中,服务器处理SQL 语句默认是以分号作为语句结束标志的,过程体中由多条 SQL 语句构成,每条 SQL 后面都是分号结尾,那么 MySQL 服务器在处理时遇到第一条 SQL 语句就会结束整个过程, 不再去处理后面的 SQL 语句。

■在创建存储过程时,使用 DELIMITER 命令
mysql> DELIMITER $$
//省略存储过程其他步骤
mysql> DELIMITER ; //分号前有空格
■要创建存储过程,必须要具有 CREATE ROUTINE 权限。

'//通过存储过程查询 player 表的三条数据,存储过程是不带参数的'
mysql> DELIMITER $$
mysql> 
CREATE PROCEDURE PlayerRole()
BEGIN
SELECT id,name,level from player limit 3;
END $$

mysql> DELIMITER ;
mysql> call PlayerRole();
+----+--------------+-------+
| id | name	| level |
+----+--------------+-------+
|   1 | 修欧拉卡	|	10 |
|   2 | 起 风了	|	10 |
|   3 | 吊打低V	|	15 |
+----+--------------+-------+
3 rows in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)

'//通过存储过程查询 player 表中某一条记录,存储过程是带参数的'
mysql>DELIMITER $$
CREATE PROCEDURE GetRole(IN inname VARCHAR(16))
BEGIN
SELECT id,name,level from player where name=inname;
END $$

mysql>DELIMITER ;
mysql>call GetRole('shirley');
+------+---------+-------+
| id	| name	| level |
+------+---------+-------+
| 2460 | shirley |	1 |
+------+---------+-------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)

3.3 修改存储过程

■存储过程在创建之后,随着开发业务的不断推进,业务需求难免有所调整,相应的存储 过程也会发生变动,这个时候就需要修改存储过程。存储过程的修改分为特征的修改和业务 内容的修改。特征的修改可以使用 ALTER PROCEDURE 来实现

■语法结构
ALTER PROCEDURE <过程名> [ <特征> … ]

■存储过程内容的修改方法是通过删除原有存储过程,之后再以相同的名称创建新的存储过程。

3.4 删除存储过程

■存储过程创建之时是存储到 MySQL 数据库中的,当程序不在调用这个存储过程时,也就意味这个存储过程被废弃了,废弃的存储过程需要从数据库中将其删除。使用 DROP PROCEDURE 语句即可删除存储过程

■语法格式
DROP { PROCEDURE | FUNCTION } [ IF EXISTS ] <过程名>
●在删除时存储过程的名字是放到最后的,前面可以添加 IF EXISTS 这个关键字,其主要作用是防止因删除不存在的存储过程而引发的错误

■删除存储过程的具体操作

mysql>DROP PROCEDURE PlayerRole; 
Query OK, 0 rows affected (0.00 sec) 

mysql>CALL PlayerRole;
ERROR 1305 (42000): PROCEDURE test.PlayerRole does not exist
'//存储过程名称后面没有参数列表,也没有括号。在删除之前,必须确认  该存储过程没有任何依赖关系,否则会导致与之关联的存储过程无法运行'