数据库存储程序有时也被称为存储模块或者存储例程,存储程序是一种被数据库服务器所存储和执行的计算机程序。
MySQL 存储程序是一组预编译的 SQL 语句集合,可以在数据库中创建和存储,然后通过调用存储过程来执行这些 SQL 语句。
MySQL 中主要有三种存储程序:存储过程、函数和触发器。
数据库存储程序有时也被称为存储模块或者存储例程,存储程序是一种被数据库服务器所存储和执行的计算机程序,存储程序的源代码(有时)可能是二进制编译版本,它几乎总是占据着数据库服务器系统的表空间,程序总是位于其数据库服务器的进程或线程的内存地址中被执行。
MySQL 中主要有三种类型的数据库存储程序:
存储过程
MySQL 存储过程是最常见的存储程序,存储过程是能够接受多个输入和输出参数并且能够在请求时被执行的程序单元。
MySQL 存储过程是一组预编译的 SQL 语句集合,可以在数据库中创建和存储,然后通过调用存储过程来执行这些 SQL 语句。
例如:创建一个名为 GetUser 的存储过程,该存储过程接受一个参数 user_id,然后根据 user_id 查询用户信息:
CREATE PROCEDURE `GetUser`(IN `user_id` int) BEGIN select * from user where id=user_id; END
执行上述脚本去创建存储过程,然后在命令行调用存储过程:
mysql> call GetUser(1); +----+-------+ | id | name | +----+-------+ | 1 | Helen | +----+-------+ 1 row in set (0.03 sec) Query OK, 0 rows affected (0.00 sec)
存储函数
MySQL 存储函数是一段预编译的 SQL 代码,可以在数据库中创建和存储,并通过调用函数来执行该代码。
MySQL 存储函数和存储过程很相像,存储函数也可以接受参数,它的执行结果会返回一个值。最重要的是存储函数可以被用来充当标准的 SQL 语句,允许程序员有效的扩展 SQL 语言的能力与存储过程类似。
例如:创建一个名为 GetUserName 的存储函数,接收一个参数 user_id,用来查询用户信息,并返回用户的姓名,如:
CREATE FUNCTION `GetUserName`(`user_id` int) RETURNS varchar(50) BEGIN -- 声明变量 DECLARE user_name VARCHAR(50) default '-'; select name into user_name from user where id=user_id; RETURN user_name; END
执行上述脚本去创建存储函数,然后在命令行调用存储函数:
mysql> select GetUserName(1); +----------------+ | GetUserName(1) | +----------------+ | Helen | +----------------+ 1 row in set (0.04 sec)
在 SQL 语句中调用存储函数:
mysql> select GetUserName(id) from user; +-----------------+ | GetUserName(id) | +-----------------+ | Helen | | Tom123hhh | | Bill 444kk | | Cay | | Gary | +-----------------+ 5 rows in set (0.05 sec)
触发器
MySQL 触发器是一种特殊的存储过程,它会在表上的特定事件发生时自动执行。触发器可以用来在插入、更新或删除表中的数据时执行一些操作。
通常,触发器用来作为 DML(数据库操纵语言)的响应而被调用,触发器可以被用来作为数据校验和自动反向格式化等。
例如:在用户表 user 上创建一个触发器,当向用户表插入数据时执行触发器,触发器将清空用户地址表的数据。
-- 用户表 CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(50) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4; -- 创建触发器 CREATE TRIGGER `insert_triger` AFTER INSERT ON `user` FOR EACH ROW delete from user_address;
执行上面脚本将在 user 表上创建一个名为 insert_triger 的触发器,然后通过如下语句去验证:
-- 查询用户表,没有数据 mysql> select * from user; Empty set -- 查询用户地址表,没有数据 mysql> select * from user_address; +----+----------+ | id | address | +----+----------+ | 1 | address1 | | 2 | address2 | +----+----------+ 2 rows in set (0.03 sec) -- 向用户表插入一条数据 mysql> insert into user(name) value('Tom'); Query OK, 1 row affected (0.05 sec) -- 查看用户表,多了一条数据 mysql> select * from user; +----+------+ | id | name | +----+------+ | 8 | Tom | +----+------+ 1 row in set (0.04 sec) -- 查看用户地址表,数据没有了 mysql> select * from user_address; Empty set
为什么使用存储过程?
开发者总是有很多种编程语言可以选择,这意味着大多数的语言并非位于数据库内,并受其管理,存储程序相对于这些多用途语言而言拥有很多优势:
(1)提高性能:存储过程在数据库服务器上执行,减少了网络传输的开销,可以显著提高查询和数据操作的性能。
(2)重用性:存储过程可以被多个应用程序和查询调用,提高了代码的重用性和维护性。
(3)安全性:存储过程可以通过访问控制和权限管理来保护敏感数据,提供更好的安全性。
(4)减少网络流量:存储过程可以将多个SQL语句组合在一起执行,减少了与数据库服务器之间的网络通信量。
(5)简化复杂操作:存储过程可以实现复杂的数据操作和业务逻辑,简化了应用程序的开发和维护。
(6)可移植性:在一定程度上可以减轻应用程序的可移植性,如将应用程序从 Java 迁移到 C#,我们不需要重新编写存储过程。如果是数据库迁移,将 mysql 迁移到其他数据库,则可移植性将非常糟糕。
MySQL 存储过程拥有很多优势的同时,还有很多劣势你需要知道,主要劣势:
(1)学习曲线:存储过程需要掌握一定的编程语言和数据库知识,对于初学者来说可能需要一定的学习曲线。
(2)维护复杂性:存储过程的复杂性可能会增加代码的维护难度,特别是当存储过程变得庞大和复杂时。
(3)依赖数据库:存储过程是在数据库服务器上执行的,因此应用程序必须与数据库紧密耦合,不适合跨数据库平台使用。
(4)可移植性:存储过程的语法和特性在不同的数据库系统中可能有所不同,不同数据库之间的存储过程不一定可以直接迁移和使用。