当前位置: 首页 > news >正文

MySql的存储过程以及JDBC实战

MySql的存储过程以及JDBC实战


文章目录

  • MySql的存储过程以及JDBC实战
  • 前言
  • 一、MySQL存储过程?
    • 1、存储过程基本语法
    • 2、存储过程示例
    • 3、注意事项
  • 二、JDBC调用存储过程的接口:CallableStatement
    • 1、核心作用
    • 2、使用步骤
    • 3、示例代码(结合 MySQL 存储过程)
    • 4、注意事项
  • 总结


前言

本次课程主要是关于Mysql的存储过程实战以及使用JDBC对存储过程进行操作。


一、MySQL存储过程?

MySQL 存储过程是一组预编译的 SQL 语句集合,封装了特定的业务逻辑,可被重复调用。它类似于编程语言中的 “函数”,能减少网络传输、提高执行效率(预编译一次,多次执行),并增强代码复用性。

1、存储过程基本语法

1.1 创建存储过程

-- 修改分隔符(避免与存储过程内的 ; 冲突)
delimiter //-- 创建存储过程
create procedure 存储过程名([参数类型] 参数名 数据类型,  -- 可选:参数(IN/OUT/INOUT)...
)
begin-- 存储过程逻辑(SQL语句、控制结构等)
end //-- 恢复默认分隔符
delimiter ; 

重点强调:一定要注意 第一行的 delimiter 与后面的 // 存在一个空格,最后一行的 delimiter 与; 存在空格

参数类型:
IN:输入参数(默认,调用时传入值,过程内可使用)。
OUT:输出参数(过程内赋值,调用后可获取结果)。
INOUT:既输入又输出(调用时传入值,过程内修改后返回)。

1.2 调用存储过程

call 存储过程名([参数值1, 参数值2, ...]);  -- 无参数时直接 call 存储过程名;

1.3 查看存储过程

-- 查看所有存储过程
show procedure status;-- 查看指定存储过程的创建语句
show create procedure 存储过程名;

1.4 删除存储过程

drop procedure if exists 存储过程名;  -- if exists 避免删除不存在的过程报错

2、存储过程示例

示例 1:无参数的存储过程(查询数据)

创建一个查询 user 表所有数据的存储过程:

delimiter //
create procedure get_all_users()
beginselect * from user;  -- 假设存在 user 表
end //
delimiter ;-- 调用
call get_all_users();

示例 2:带 IN 参数的存储过程(条件查询)

根据用户 ID 查询用户信息:

delimiter //
create procedure get_user_by_id(in user_id int)  -- 输入参数 user_id
beginselect * from user where id = user_id;
end //
delimiter ;-- 调用(查询 ID=1 的用户)
call get_user_by_id(1);

示例 3:带 OUT 参数的存储过程(返回结果)

计算 user 表的总记录数,并通过输出参数返回:

delimiter //
create procedure get_user_count(out total int)  -- 输出参数 total
beginselect count(*) into total from user;  -- 将结果存入 total
end //
delimiter ;-- 调用(需先定义变量接收结果)
set @total_count = 0;  -- 定义用户变量
call get_user_count(@total_count);  -- 传入变量
select @total_count as user_total;  -- 查看结果

示例 4:带 INOUT 参数的存储过程(修改并返回值)

将输入的数字翻倍后返回:

delimiter //
create procedure double_number(inout num int)  -- 既输入又输出
beginset num = num * 2;  -- 修改参数值
end //
delimiter ;-- 调用
set @n = 5;  -- 初始值 5
call double_number(@n);  -- 传入并修改
select @n;  -- 结果为 10

示例 5:包含控制结构的存储过程(条件 + 循环)

根据年龄范围批量插入用户(使用 if 条件和 while 循环):

delimiter //
create procedure batch_insert_users(in start_age int,  -- 起始年龄in end_age int     -- 结束年龄
)
begindeclare current_age int;  -- 声明局部变量set current_age = start_age;  -- 初始化-- 循环插入while current_age <= end_age do-- 条件判断:年龄>30 则状态为 'adult',否则为 'young'if current_age > 30 theninsert into user(name, age, status) values(concat('user_', current_age), current_age, 'adult');elseinsert into user(name, age, status) values(concat('user_', current_age), current_age, 'young');end if;set current_age = current_age + 1;  -- 自增end while;
end //
delimiter ;-- 调用(插入年龄 20-22 的用户)
call batch_insert_users(20, 22);

3、注意事项

分隔符问题:创建存储过程时必须用 delimiter 修改分隔符(如 //),否则 MySQL 会将过程内的 ; 视为语句结束,导致语法错误。
变量命名:局部变量(declare 声明)仅在过程内有效,避免与表列名或参数名冲突。
权限:创建存储过程需要 CREATE ROUTINE 权限,执行需要 EXECUTE 权限。
调试:MySQL 存储过程调试相对复杂,可通过 select 输出中间结果辅助调试。
适用场景:适合复杂业务逻辑(如多表关联、批量操作),但过度使用可能导致维护困难(建议简单逻辑直接用 SQL 语句)。
通过以上示例,可快速掌握存储过程的创建、调用和常见用法。根据实际业务需求,可组合 SQL 语句和控制结构(if/case/while/repeat 等)实现复杂功能。

二、JDBC调用存储过程的接口:CallableStatement

在 JDBC 中,CallableStatement 是一个接口(继承自 PreparedStatement),专门用于调用数据库中的存储过程。它支持存储过程的输入参数(IN)、输出参数(OUT)和输入输出参数(INOUT),并能处理存储过程的返回结果。

1、核心作用

  • 执行数据库存储过程(如 MySQL、Oracle 等的 PROCEDURE)。
  • 支持存储过程的参数传递(IN/OUT/INOUT)。
  • 相比直接执行 SQL 语句,调用存储过程可减少网络交互,提高效率(尤其适合复杂逻辑)。

2、使用步骤

1.获取数据库连接(Connection)。
2.编写调用存储过程的 SQL 模板:使用 {call 存储过程名(参数列表)} 格式(参数用 ? 占位)。
3.创建 CallableStatement 对象:通过connection.prepareCall(sql) 生成。
4.处理参数:

  • 输入参数(IN):用 setXxx(索引, 值) 方法设置(如 setInt(1, 100))。
  • 输出参数(OUT):用 registerOutParameter(索引, SQL类型) 注册(如 registerOutParameter(2, Types.INTEGER))。
  • 输入输出参数(INOUT):先 setXxx 设输入值,再 registerOutParameter 注册输出类型。
    5.执行存储过程:调用 execute() 方法。
    6.获取结果:通过 getXxx(索引) 方法获取输出参数或返回结果。
    7.关闭资源:关闭 CallableStatement 和 Connection(建议用 try-with-resources 自动关闭)。

3、示例代码(结合 MySQL 存储过程)

假设已在 MySQL 中创建以下存储过程,分别演示 IN/OUT/INOUT 参数:

  1. 带 IN 参数的存储过程(查询用户信息)
-- 存储过程:根据用户ID查询用户名
DELIMITER //
CREATE PROCEDURE get_username_by_id(IN user_id INT)
BEGINSELECT username FROM users WHERE id = user_id;
END //
DELIMITER ;

JDBC 调用代码:

import java.sql.*;public class CallableDemo1 {public static void main(String[] args) {// 数据库连接信息String url = "jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTC";String user = "root";String password = "your_password";// 调用存储过程的SQL模板String sql = "{call get_username_by_id(?)}";  // ? 对应 IN 参数 user_idtry (Connection conn = DriverManager.getConnection(url, user, password);CallableStatement cstmt = conn.prepareCall(sql)) {// 设置 IN 参数(索引从1开始,值为1)cstmt.setInt(1, 1);// 执行存储过程ResultSet rs = cstmt.executeQuery();  // 有返回结果集时用 executeQuery()// 处理结果if (rs.next()) {String username = rs.getString("username");System.out.println("用户名:" + username);}} catch (SQLException e) {e.printStackTrace();}}
}
  1. 带 OUT 参数的存储过程(返回用户总数)
-- 存储过程:返回用户表总记录数(通过 OUT 参数输出)
DELIMITER //
CREATE PROCEDURE get_user_count(OUT total INT)
BEGINSELECT COUNT(*) INTO total FROM users;
END //
DELIMITER ;

JDBC 调用代码:

import java.sql.*;public class CallableDemo2 {public static void main(String[] args) {String url = "jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTC";String user = "root";String password = "your_password";String sql = "{call get_user_count(?)}";  // ? 对应 OUT 参数 totaltry (Connection conn = DriverManager.getConnection(url, user, password);CallableStatement cstmt = conn.prepareCall(sql)) {// 注册 OUT 参数(索引1,类型为整数)cstmt.registerOutParameter(1, Types.INTEGER);// 执行存储过程(无结果集时用 execute())cstmt.execute();// 获取 OUT 参数的值int total = cstmt.getInt(1);System.out.println("用户总数:" + total);} catch (SQLException e) {e.printStackTrace();}}
}
  1. 带 INOUT 参数的存储过程(修改并返回值)
-- 存储过程:将输入的数字翻倍后返回(INOUT 参数)
DELIMITER //
CREATE PROCEDURE double_number(INOUT num INT)
BEGINSET num = num * 2;
END //
DELIMITER ;

JDBC 调用代码:

import java.sql.*;public class CallableDemo3 {public static void main(String[] args) {String url = "jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTC";String user = "root";String password = "your_password";String sql = "{call double_number(?)}";  // ? 对应 INOUT 参数 numtry (Connection conn = DriverManager.getConnection(url, user, password);CallableStatement cstmt = conn.prepareCall(sql)) {// 设置 INOUT 参数的初始值(输入)cstmt.setInt(1, 5);  // 初始值 5// 注册 INOUT 参数的输出类型cstmt.registerOutParameter(1, Types.INTEGER);// 执行存储过程cstmt.execute();// 获取修改后的值(输出)int result = cstmt.getInt(1);System.out.println("翻倍后的值:" + result);  // 输出 10} catch (SQLException e) {e.printStackTrace();}}
}

4、注意事项

  • 参数索引:CallableStatement 的参数索引从 1 开始(而非 0)。
  • 输出参数注册:OUT 和 INOUT 参数必须先通过 registerOutParameter 注册 SQL 类型(如 Types.INTEGER、Types.VARCHAR),否则会抛出异常。
  • 执行方法选择:
    存储过程返回结果集时,用 executeQuery()。
    无结果集但有输出参数时,用 execute()。
  • SQL 类型对应:registerOutParameter 的第二个参数需与数据库字段类型对应(如 MySQL 的 INT 对应 Types.INTEGER,VARCHAR 对应 Types.VARCHAR)。
    资源关闭:始终确保 Connection、CallableStatement、ResultSet 被关闭(try-with-resources 是最佳实践)。
    通过 CallableStatement,JDBC 可以灵活调用各种存储过程,尤其适合需要复用数据库逻辑的场景。

总结

以上就是今天要讲的内容,本文仅仅简单介绍了MySQL的存储过程的使用,以及JDBC的相关接口。

http://www.dtcms.com/a/426885.html

相关文章:

  • 中国电建地产北京山谷:以“三好”战略绘就文旅康养与乡村振兴融合新图景
  • 中国网站建设中心做旅游网站公司
  • 【PyCharm】远程本地的WSL2如何配置copilot的Tab不冲突
  • 49.多路转接epoll
  • flash网站源码下载北京网站建设案例
  • 景德镇做网站代理游戏平台赚钱吗
  • 开源AI大模型、AI智能名片与S2B2C商城小程序:用户需求满足的底层逻辑与实践路径
  • Git 命令配置别名、Git命令缩写(Mac版)
  • 部署Tomcat11.0.11(Kylinv10sp3、Ubuntu2204、Rocky9.3)
  • SCL-90症状自评量表抖音快手微信小程序看广告流量主开源
  • 合肥网站公司微信商城开发需要多少钱
  • 企业在拥抱 Al技术过程中面临安全风险是什么
  • Claude Sonnet 4.5:一次面向落地的常规升级(性能、安全、开发者工具)
  • Linux内核命名空间隔离机制在容器安全强化中的实战应用标准
  • 灵雀云六度入选 Gartner 中国 ICT 技术成熟度曲线报告,ACP以安全、稳定、智能三大核心能力定义企业级云原生数字底座
  • 中文的网站做不成二维码记事本做网站怎么改字体颜色
  • 近场通讯(NFC)在工厂智能化中的应用:从工具管理到身份识别
  • 计算机网络-RIP协议
  • Cortex-M3深入理解
  • python进阶_Day2
  • Python14-SVM⽀持向量机
  • 无锡做网站价格手机网站排名怎么做
  • 大模型价格战背后的技术革命:剖析DeepSeek-V3.2的DSA稀疏注意力
  • 用 AI 驱动 Unity 开发:Unity3d MCP
  • 微信小程序学习(四)
  • VIM和Linux命令速查表
  • TDengine 时序函数 STATECOUNT 用户手册
  • GitHub Spec Kit:官方规格驱动开发工具包深度解析
  • 商标图片大全 设计图网站过度优化的表现
  • 精读C++20设计模式——行动型设计模式:责任链