drop table if exists user;
create table user(
id int auto_increment primary key,
name varchar(20),
sex enum('female', 'male') default 'male',
balance float(8, 2),
register_time datetime);
truncate user;
insert user(name, sex, balance, register_time)
values('bruce', 'male', 1642.79, '2022-07-01 10:21:31'),
('alice', 'female', 2546.55, '2022-07-02 12:45:20'),
('john', 'male', 125.74, '2022-08-03 08:15:47'),
('emma', 'female', 2651.23, '2022-08-04 16:30:12'),
('mike', 'male', 852.90, '2022-09-05 09:54:38');
流程控制是编程中一种用于控制程序执行流程的机制,通常涉及条件判断、循环和分支等结构。
在数据库中的存储过程、触发器、以及一些脚本语言中,流程控制结构用于根据不同条件执行不同的代码块,从而实现更为复杂和灵活的逻辑。
在数据库中,流程控制结构的主要目的是在 SQL 语句的基础上提供更强大的编程能力,使得可以实现更复杂的业务逻辑。
系统变量是 MySQL 服务器上的全局配置参数,它们影响着 MySQL 的整体行为。
可以使用 SHOW VARIABLES;
查询当前服务器上的所有系统变量。
例如:
show variables like 'max_connections';
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| max_connections | 200 |
+-----------------+-------+
@
符号为前缀。set @name = 'bruce';
select @name;
在存储过程中,可以声明局部变量,这些变量仅在存储过程的执行期间存在,超出存储过程的范围后被销毁。
语法:
declare 变量名 类型
if 条件 then
-- 执行内容
elseif 条件 then
-- 执行内容
else
-- 执行内容
end if;
case
when 条件1 then
-- 执行内容
when 条件2 then
-- 执行内容
......
else
-- 执行内容
end case;
while 条件 do
-- 执行内容
end while;
repeat
-- 执行内容
until 条件;
loop
-- 执行内容
end loop;
for 变量 in 多内容 do
-- 执行内容
end for;
while 条件 do
-- 执行内容
if 条件 then
leave;
end if;
end while;
命令式开发模式(Imperative Development Model)
存储过程以类似编程语言的方式编写,包括条件语句、循环结构和异常处理等。
逻辑较为灵活,但容易导致存储过程复杂难懂,维护困难。
声明式开发模式(Declarative Development Model)
存储过程的逻辑更关注数据操作语句,如查询、插入、更新和删除等。
通过声明数据操作的目标和条件来实现,逻辑简洁明了,更易于理解和维护。
触发器开发模式(Trigger Development Model)
触发器是一种特殊的存储过程,与数据库表相关联,在预定义的事件发生时自动触发执行。
用于实现数据一致性、数据验证、日志记录等功能。
开发模式与其他存储过程略有不同,执行时机和上下文由数据库事件触发,而不是外部调用。
delimiter $$
create procedure 存储器名(in 形参 类型, in 形参 类型, out 形参 类型)
begin
--执行语句
end $$
delimiter ;
delimiter $$
create procedure my_func_recharge(in n varchar(20), in m float(8, 2), out res varchar(20))
begin
declare name_exists int;
select count(*) into name_exists
from user where name = n;
if name_exists > 0 then
update user
set balance = balance + m
where name = n;
set res = '充值成功';
else
set res = '充值失败,名字不存在';
end if;
end $$
delimiter ;
show create procedure 存储过程名字 \G;
show create procedure my_func_recharge \G;
mysql> show create procedure my_func_recharge \G;
*************************** 1. row ***************************
Procedure: my_func_recharge
sql_mode: ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,PAD_CHAR_TO_FULL_LENGTH
Create Procedure: CREATE DEFINER=`root`@`localhost` PROCEDURE `my_func_recharge`(in n varchar(20), in m float(8, 2), out res varchar(20))
begin
declare name_exists int;
select count(*) into name_exists
from user where name = n;
if name_exists > 0 then
update user
set balance = balance + m
where name = n;
set res = '充值成功';
else
set res = '充值失败,名字不存在';
end if;
end
character_set_client: utf8mb4
collation_connection: utf8mb4_general_ci
Database Collation: utf8mb4_general_ci
1 row in set (0.00 sec)
ERROR:
No query specified
show procedure status;
call 存储过程名字(参数);
# 查看原来的金额
select balance from user where name = 'bruce';
+---------+
| balance |
+---------+
| 1642.79 |
+---------+
# 充值测试
set @res = ''
call my_func_recharge('bruce', 100.5, @res);
# 查看标志位
select @res;
+--------------+
| @res |
+--------------+
| 充值成功 |
+--------------+
# 查看金额
+---------+
| balance |
+---------+
| 1743.29 |
+---------+
# 名字错误测试
call my_func_recharge('bbruce', 100.5, @res);
select @res;
+--------------------------------+
| @res |
+--------------------------------+
| 充值失败,名字不存在 |
+--------------------------------+
drop procedure if exists 存储过程名称;
drop procedure if exists my_func_recharge;
CONCAT
: 将多个字符串拼接在一起。select concat(id, "-", name) as id_name
from user limit 2;
+---------+
| id_name |
+---------+
| 1-bruce |
| 2-alice |
+---------+
SUBSTRING
: 截取字符串的子串。select substring('python', 3, 2) as res;
+------+
| res |
+------+
| th |
+------+
CHAR_LENGTH
: 返回字符串的字符数。select name, char_length(name) as name_length
from user limit 3;
+-------+-------------+
| name | name_length |
+-------+-------------+
| bruce | 5 |
| alice | 5 |
| john | 4 |
+-------+-------------+
select upper(name) as name
from user limit 3;
+-------+
| name |
+-------+
| BRUCE |
| ALICE |
| JOHN |
+-------+
ROUND(num, decimals)
: 对数值进行四舍五入。select balance as old, round(balance) as new
from user limit 3;
+---------+------+
| old | new |
+---------+------+
| 1743.29 | 1743 |
| 2546.55 | 2547 |
| 125.74 | 126 |
+---------+------+
FLOOR(num)
: 返回不大于给定数值的最大整数。select balance as old, floor(balance) as new
from user limit 3;
+---------+------+
| old | new |
+---------+------+
| 1743.29 | 1743 |
| 2546.55 | 2546 |
| 125.74 | 125 |
+---------+------+
CEILING(num)
: 返回不小于给定数值的最小整数。select balance as old, ceiling(balance) as new
from user limit 3;
+---------+------+
| old | new |
+---------+------+
| 1743.29 | 1744 |
| 2546.55 | 2547 |
| 125.74 | 126 |
+---------+------+
ABS(num)
: 返回给定数值的绝对值。NOW()
: 返回当前日期和时间。select now() as time;
+---------------------+
| time |
+---------------------+
| 2024-01-30 21:07:15 |
+---------------------+
CURDATE()
: 返回当前日期。select curdate() as today;
+------------+
| today |
+------------+
| 2024-01-30 |
+------------+
CURTIME()
: 返回当前时间。select curtime() as time;
+----------+
| time |
+----------+
| 21:09:56 |
+----------+
DATE_FORMAT(date, format)
: 格式化日期。select date_format(register_time, '%Y-%m') as date, count(*)
from user
group by date_format(register_time, '%Y-%m');
+---------+----------+
| date | count(*) |
+---------+----------+
| 2022-07 | 2 |
| 2022-08 | 2 |
| 2022-09 | 1 |
+---------+----------+
select * from user where date(register_time) = '2022-08-03';
+----+------+------+---------+---------------------+
| id | name | sex | balance | register_time |
+----+------+------+---------+---------------------+
| 3 | john | male | 125.74 | 2022-08-03 08:15:47 |
+----+------+------+---------+---------------------+
select * from user year
where month(register_time) = '07';
+----+-------+--------+---------+---------------------+
| id | name | sex | balance | register_time |
+----+-------+--------+---------+---------------------+
| 1 | bruce | male | 1642.79 | 2022-07-01 10:21:31 |
| 2 | alice | female | 2546.55 | 2022-07-02 12:45:20 |
+----+-------+--------+---------+---------------------+
详细信息查看筛选条件的group by
COUNT(column)
: 计算符合条件的行数。
SUM(column)
: 对指定列的值求和。
AVG(column)
: 计算指定列的平均值。
MIN(column)
: 找到指定列的最小值。
MAX(column)
: 找到指定列的最大值。
GROUP_CONCAT
:拼接字段值或字符串。
IF(condition, value_if_true, value_if_false): 如果条件成立,则返回value_if_true,否则返回value_if_false。
select name, if(balance > 2000, "rich", "poor") as money_con
from user;
+-------+-----------+
| name | money_con |
+-------+-----------+
| bruce | poor |
| alice | rich |
| john | poor |
| emma | rich |
| mike | poor |
+-------+-----------+
CASE WHEN condition THEN value END: 根据满足的条件返回相应的值。
select name,
case
when balance > 2500 then 'very rich'
when balance > 2000 then 'rich'
else
'poor'
end as money_con
from user;
+-------+-----------+
| name | money_con |
+-------+-----------+
| bruce | poor |
| alice | very rich |
| john | poor |
| emma | very rich |
| mike | poor |
+-------+-----------+