数据库编程必杀技:解锁存储过程与函数的秘密数据库编程看似高深莫测,但掌握了存储过程与存储函数,你就能轻松驾驭复杂的业务逻辑,提高效率,甚至让数据库“听你指挥”!这些隐藏在数据库中的“必杀技”不仅能优化性能,还能让代码更优雅、安全性更高。本文将带你揭开存储过程与函数的神秘面纱,从基础到实战,手把手教
数据库编程看似高深莫测,但掌握了存储过程与存储函数,你就能轻松驾驭复杂的业务逻辑,提高效率,甚至让数据库“听你指挥”!这些隐藏在数据库中的“必杀技”不仅能优化性能,还能让代码更优雅、安全性更高。本文将带你揭开存储过程与函数的神秘面纱,从基础到实战,手把手教你解锁它们的秘密,助你在数据库编程的道路上一飞冲天!
本文为你献上一套数据库编程的“必杀技”——存储过程与存储函数的全面解析!存储过程是一组预编译的SQL“武器”,能高效完成特定任务,兼具高性能与安全性;而存储函数则以灵活的返回值,解决精准计算需求。我们将从基本概念入手,深入讲解创建方法、流程控制、游标操作等技巧,并通过MySQL实战案例带你上手。想知道如何用最少的代码实现最大的效率?这里有你想要的所有秘密!
DELIMITER 命令的使用语法格式是:
DELIMITER $$$$ 是用户定义的结束符,通常这个符号可以是一些特殊的符号,例如两个“#”,或两个“¥”等DELIMITER 命令时,应该避免使用反斜杠(“\”)字符,因为它是MySQL的转义字符例子:将 MySQL 结束符修改为两个感叹号“!!”。
mysql> DELIMITER !!换回默认的分行“;”
mysql> DELIMITER ;创建存储过程
CREATE PROCEDURE sp_name ([proc_parameter[,...]])
 routine_body"proc_parameter" 的语法格式:
[IN | OUT | INOUT] param_name type
# 参数的取名不要与数据表的列名相同例子:在数据库 mysql_test 中创建一个存储过程,用于实现给定表 customers 中一个客户 id 号即可修改表 customers 中该客户的性别为一个指定的性别。
➜ mysql -uroot -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1850
Server version: 8.0.32 Homebrew
Copyright (c) 2000, 2023, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> use mysql_test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> delimiter $$
mysql> create procedure sp_update_sex(in cid int,in csex char(1))
    -> begin
    -> update customers set cust_sex=csex where cust_id=cid;
    -> end $$
Query OK, 0 rows affected (0.03 sec)
mysql>DECLARE var_name[,...] type [DEFAULT value]例子:声明一个整形局部变量 cid。
DECLARE cid INT(10);SET var_name = expr [, var_name = expr] ...例子:为声明的局部变量 cid 赋予一个整数值 910
SET cid=910;SELECT col_name [,...] INTO var_name[,...] table_expr在MySQL中,使用游标的具体步骤如下:
DECLARE cursor_name CURSOR FOR select_statementOPEN cursor_nameFETCH cursor_name INTO var_name [, var_name] ...CLOSE cursor_name例子:在数据库 mysql_test 中创建一个存储过程,用于计算表 customers 中数据行的行数。
首先,在MySQL命令行客户端输入如下 SQL语句创建存储过程 sq_sumofrow:
➜ mysql -uroot -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2286
Server version: 8.0.32 Homebrew
Copyright (c) 2000, 2023, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> use mysql_test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> delimiter $$
mysql> create procedure sp_sumofrow(OUT ROWS INT)
    -> begin
    -> declare cid int;
    -> declare found boolean default true;
    -> declare cur_cid cursor for
    -> select cust_id from customers;
    -> declare continue handler for not found
    -> set found=false;
    -> set rows=0;
    -> open cur_cid;
    -> fetch cur_cid into cid;
    -> while found do
    -> set rows=rows+1;
    -> fetch cur_cid into cid;
    -> end while;
    -> close cur_cid;
    -> end$$
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'ROWS INT)
begin
declare cid int;
declare found boolean default true;
declare cur' at line 1
mysql> 
mysql> CREATE PROCEDURE sp_sumofrow(OUT ROWS INT)
    -> BEGIN
    -> DECLARE cid INT;
    -> DECLARE FOUND BOOLEAN DEFAULT TRUE;
    -> DECLARE cur_cid CURSOR FOR
    -> SELECT cust_id FROM customers;
    -> DECLARE CONTINUE HANDLER FOR NOT FOUND
    -> SET FOUND=FALSE;
    -> SET ROWS=0;
    -> OPEN cur_cid;
    -> FETCH cur_cid INTO cid;
    -> WHILE FOUND DO
    -> SET ROWS=ROWS+1;
    -> FETCH cur_cid INTO cid;
    -> END WHILE;
    -> CLOSE cur_cid;
    -> END$$
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'ROWS INT)
BEGIN
DECLARE cid INT;
DECLARE FOUND BOOLEAN DEFAULT TRUE;
DECLARE cur' at line 1
mysql>
mysql> CREATE PROCEDURE sp_sumofrow(OUT `ROWS` INT) BEGIN DECLARE cid INT; DECLARE FOUND BOOLEAN DEFAULT TRUE; DECLARE cur_cid CURSOR FOR SELECT cust_id FROM customers; DECLARE CONTINUE HANDLER FOR NOT FOUND SET FOUND=FALSE; SET `ROWS`=0; OPEN cur_cid; FETCH cur_cid INTO cid; WHILE FOUND DO SET `ROWS`=`ROWS`+1; FETCH cur_cid INTO cid; END WHILE; CLOSE cur_cid; END$$
Query OK, 0 rows affected (0.01 sec)
mysql>然后,在 MySQL 命令行客户端输入如下 SQL语句对存储过程 sp_sumofrow 进行调用:
mysql> call sp_sumofrow(@rows);
    ->
    ->
    -> $$
Query OK, 0 rows affected (0.01 sec)
mysql> delimiter ;
mysql> select @rows;
+-------+
| @rows |
+-------+
|     4 |
+-------+
1 row in set (0.00 sec)
mysql>最后,查看调用存储过程 sp_sumofrow后的结果:
mysql> select @rows;
+-------+
| @rows |
+-------+
|     4 |
+-------+
1 row in set (0.00 sec)
mysql>由此例可以看出:
在使用游标的过程中,需要注意以下几点:
CALL sp_name([parameter[,...]])
CALL sp_name[()]例子:调用数据库 mysql_test 中的存储过程 sp_update_sex,将客户 id 号位 909 的客户性别修改为男性“M”。
mysql> call sp_update_sex(909,'M');
Query OK, 0 rows affected (0.00 sec)
mysql>
DROP PROCEDURE [IF EXISTS] sp_name例子:删除数据库 mysql_test 中的存储过程 sp_update_sex。
mysql> DROP PROCEDURE sp_update_sex;
Query OK, 0 rows affected (0.01 sec)
mysql>存储函数与存储过程的区别:
CREATE FUNCTION sp_name ([func_parameter[,...]])
 RETURNS type
 routine_body其中,语法项“func_parameter”的语法格式是:
param_name type例子:在数据库 mysql_test 中创建一个存储函数,要求该函数能根据给定的客户 id 号返回客户的性别,如果数据库中没有给定的 id 号,则返回“没有该客户”。
➜ mysql -uroot -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 659
Server version: 8.0.32 Homebrew
Copyright (c) 2000, 2023, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> use mysql_test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> DELIMITER $$
mysql> CREATE FUNCTION fn_search(cid INT)
    -> RETURNS CHAR(2)
    -> DETERMINISTIC
    -> BEGIN
    -> DECLARE SEX CHAR(2);
    -> SELECT cust_sex INTO SEX FROM customers
    -> WHERE cust_id=cid;
    -> IF SEX IS NULL THEN
    -> RETURN(SELECT '没有该客户');
    -> ELSE IF SEX='F' THEN
    -> RETURN(SELECT '女');
    -> ELSE RETURN(SELECT '男');
    -> END IF;
    -> END IF;
    -> END $$
Query OK, 0 rows affected (0.02 sec)
mysql>
SELECT sp_name ([func_parameter[,...]])例子:调用数据库 mysql_test 中的存储函数 fn_search。
mysql> delimiter ;
mysql> SELECT fn_search(904);
+----------------+
| fn_search(904) |
+----------------+
| 男             |
+----------------+
1 row in set (0.00 sec)
mysql>DROP FUNCTION [IF EXISTS] sp_name例子:删除数据库 mysql_test 中的存储函数 fn_search。
mysql> DROP FUNCTION IF EXISTS fn_search;
Query OK, 0 rows affected (0.00 sec)
mysql>
存储过程与存储函数,堪称数据库编程中的“双剑合璧”。通过本文,你不仅掌握了它们的创建与调用,还学会了用游标、变量等技巧解锁更复杂的操作。存储过程让你批量处理如虎添翼,存储函数让结果返回精准高效。无论是优化性能、减少流量,还是提升安全性,这些“必杀技”都能助你事半功倍。赶快将这些秘密应用到你的项目中,开启数据库编程的新篇章吧!
 
                如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!