mysq--存储过程示例--各种存储过程的创建和执行

本文深入探讨了SQL存储过程的创建与应用,包括插入、查询、更新和删除等常见操作,展示了如何利用存储过程提高数据库操作效率,防止SQL注入,并提供了Navicat中的具体示例。

与java相比,用sql语句对数据查询结果做基础的数据操逻辑处理有更高的效率,从而可以提升系统的运行速度,而存储过程作为数据操作的一个重要工具,个人认为,作为一个经常与数据库打交道的 java程序员有必要了解一下,存储过程不仅可以提升查询效率,更可以完成大部分的数据逻辑处理,还可以有效防止SQL注入式攻击。

创建数据库表,用于测试

tb_user(id,name,sex,age)

drop table if EXISTS tb_user;
create table tb_user(
id int(11) primary key auto_increment,
name varchar(18) default null,
sex char(2) default null,
age int(11) default null
);

查看表结构

select * from tb_user;

插入一行记录

insert into tb_user(name,sex,age) values(‘张三丰’,‘男’,130);

查看表数据

select * from tb_user;

编写存储过程并测试

插入数据的存储过程

	DROP PROCEDURE IF EXISTS insert_user;
		DELIMITER // #这条命令是mysql容器解释的,该段命令是否已经结束,mysql是否可以执行了,在默认情况下,分号就是结束;
	# 存储过程头部分	
	CREATE PROCEDURE insert_user
		(
			OUT v_id INTEGER,			#出参,即返回时使用
			IN v_name VARCHAR(18), 	#入参
			IN v_sex VARCHAR(19),		#入参
			IN v_age INTEGER)				#入参
		#存储过程体
	BEGIN
		# 执行insert操作,values中的值是传入的参数
		INSERT INTO tb_user(NAME,sex,age) VALUES(v_name,v_sex,v_age);
		# 将insert成功自动生成的主键id值设置到变量v_id中返回
		SET v_id = LAST_INSERT_ID();
	END;
<!--mybatis使用时mapper.xml文件的写法-->
  <insert id="saveUser" parameterType="com.zfh.domain.User" statementType="CALLABLE">
  	{
  		call insert_user(
  			#{id,mode=OUT,jdbcType=INTEGER},
  			#{name,mode=IN},
  			#{sex,mode=IN},
  			#{age,mode=IN}
  		)
  	}
  </insert>

查询所有数据的存储过程

DROP PROCEDURE IF EXISTS select_user;
DELIMITER //
CREATE PROCEDURE select_user()
BEGIN
SELECT id,NAME,sex,age FROM tb_user;
END

<!--mybatis使用时mapper.xml文件的写法-->
   <select id="selectUser" resultType="com.zfh.domain.User" statementType="CALLABLE">
  	{
  		call select_user()
  	}
  </select>

根据id查询数据的存储过程

DROP PROCEDURE IF EXISTS select_user_by_id;
DELIMITER //
CREATE PROCEDURE select_user_by_id(IN v_id INTEGER)
BEGIN
SELECT id,NAME,sex,age FROM tb_user WHERE id = v_id;
END

<!--mybatis使用时mapper.xml文件的写法-->
    <select id="selectUserById" parameterType="int" resultType="com.zfh.domain.User" statementType="CALLABLE">
  	{
  		call select_user_by_id(
  			#{id,mode=IN}
  		)
  	}
  </select>

修改数据的存储过程

DROP PROCEDURE IF EXISTS update_user;
DELIMITER //
CREATE PROCEDURE update_user
(
IN v_id INTEGER,
IN v_name VARCHAR(18),
IN v_sex VARCHAR(19),
IN v_age INTEGER)
BEGIN
UPDATE tb_user SET NAME = v_name,sex = v_sex,age = v_age
WHERE id = v_id;
END

<!--mybatis使用时mapper.xml文件的写法-->
   <update id="modifyUser" parameterType="com.zfh.domain.User" statementType="CALLABLE">
  	{
  		call update_user(
  			#{id,mode=IN},
  			#{name,mode=IN},
  			#{sex,mode=IN},
  			#{age,mode=IN}
  		)
  	}
  </update>

删除数据的存储过程

DROP PROCEDURE IF EXISTS delete_user_by_id;
DELIMITER //
CREATE PROCEDURE delete_user_by_id(IN v_id INTEGER)
BEGIN
DELETE FROM tb_user WHERE id = v_id;
END

<!--mybatis使用时mapper.xml文件的写法-->
   <delete id="removeUser" parameterType="com.zfh.domain.User" statementType="CALLABLE">
  	{
  		call delete_user_by_id(
  			#{id,mode=IN}
  		)
  	}
  </delete>

在navicat中的写法和用法

select * from tb_user;
call select_user_by_id(2);
SELECT id,NAME,sex,age FROM tb_user WHERE id = 2;

更多的MYSQL存储过程操作

使用SHOW STATUS查看状态

SHOW STATUS查看存储过程和函数的状态,语法如下:
SHOW {PROCEDURE | FUNCTION} STATUS [LIKE ‘parttern’]
这个语句是MySQL的扩展,它返回子程序的特征,如数据库、名字、类型、创建者及创建和修改日期。如果没有指定样式,根据使用的语句,所有存储程序或存储函数的信息都被列出。PROCEDURE和FUNCTION分别表示查看存储过程和函数;LIKE语句表示匹配存储过程或函数名称。
示例:
SHOW PROCEDURE STATUS LIKE ‘proc_%’;

使用SHOW CREATE查看定义

使用SHOW CREATE语句查看存储过程和函数的状态,语法如下:
SHOW CREATE {PROCEDURE | FUNCTION} proc_or_func
这个语句是一个MySQL的扩展,类似于SHOW CREATE TABLE,它返回一个可用来重新创建已命名子程序的确切字符串。PROCEDURE和FUNCTION分别表示查看存储过程和函数,proc_or_func表示匹配存储过程或函数名。
示例:
SHOW CREATE PROCEDURE proc_countByName;

从information_schema.Routines查看信息

MySQL存储过程和函数的信息存储在information_schema数据库下的Routines表中。通过查询该表的记录查询信息,SQL如下:
SELECT * FROM information_schema.ROUTINES
WHERE ROUTINE_NAME = ‘proc_or_func’

### MySQL 查询执行过程详解 MySQL 查询的执行过程可以分为多个阶段,这些阶段共同协作完成用户的查询请求。以下是详细的分析: #### 1. 客户端发送查询到服务器 当用户通过客户端提交一条 SQL 查询时,该查询会被发送至 MySQL 数据库服务器。此时,MySQL 开始处理这条查询。 #### 2. 解析器 (Parser) 在接收到查询后,MySQL 使用解析器验证 SQL 语句的语法正确性,并将其转换为内部表示形式。如果发现任何语法错误,则立即返回错误消息[^1]。 #### 3. 权限检查 (Privilege Check) 在此阶段,MySQL 检查当前用户是否有足够的权限来访问涉及的对象(如表、列等)。如果没有适当权限,查询将被终止并返回相应的错误信息[^2]。 #### 4. 查询缓存 (Query Cache) 如果启用了查询缓存机制,MySQL 会在这一阶段尝试查找是否存在相同的查询及其结果集。如果有匹配项,则直接返回缓存中的结果而无需进一步执行其他步骤;否则继续后续流程[^5]。 #### 5. 查询优化器 (Optimizer) 这是整个过程中非常重要的一个环节。查询优化器负责生成多种可能的执行计划,并从中挑选出代价最低的一种作为最终方案。它考虑的因素包括但不限于索引的选择、联接顺序以及子查询重写等方面[^3]。 可以通过以下命令查看最近一次查询的成本估算值: ```sql SHOW STATUS LIKE 'Last_query_cost'; ``` #### 6. 执行器 (Executor) 一旦确定了最佳执行路径,执行器便依据此计划逐步操作底层存储引擎以获取所需的数据记录。具体来说,它会调用相应存储引擎提供的 API 接口来进行实际的数据读取/更新工作[^2]。 对于复杂的查询而言,比如带有聚合函数 (`GROUP BY`) 排序 (`ORDER BY`) 的情况,可能会涉及到临时表创建或文件排序等额外开销较大的动作[^4]。 #### 7. 返回结果给客户端 最后,在完成了所有必要的计算之后,MySQL 将把最终的结果集打包并通过网络传输回发起请求的那个客户端应用那里去展示出来[^2]。 --- ### 示例代码 下面给出一段简单的例子说明如何利用上述理论知识编写高效查询: 假设存在一张名为 `orders` 的订单表格,其中包含字段 `order_id`, `customer_id`, `product_name`, 及其价格 `price`. 若要找出每位顾客购买商品总数超过两件的情况可按如下方式构建SQL: ```sql SELECT customer_id,COUNT(*) as total_items FROM orders WHERE price > 10 -- 假设只统计单价高于十元的商品 GROUP BY customer_id HAVING COUNT(*) >=2 ORDER BY total_items DESC; ``` 以上述为例解释各步作用: - **过滤**: WHERE 子句用于筛选符合条件的部分. - **分组与计数**: GROUP BY 结合 COUNT 函数实现分类汇总目的. - **二次过滤**: HAVING 进一步限定满足特定数量阈值以上的群体. - **排序呈现**: ORDER BY 控制输出次序以便直观理解. ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值