2021-06-09
Posted Gelcon.
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021-06-09相关的知识,希望对你有一定的参考价值。
使用Java连接mysql8.0并调用存储过程和函数
参考网站
Java连接MySQL,调用存储过程和函数
https://blog.csdn.net/qq_43521551/article/details/107097112
MySQL自定义函数
https://www.cnblogs.com/progor/p/8871480.html
2.1 对学生课程数据库,编写存储过程,完成下面功能:
1)统计离散数学的成绩分布情况,即按照各分数段统计人数;
2)统计任意一门课的平均成绩。
3)将学生选课成绩从百分制改为等级制(即A、B、C、D、E);
要求:提交源程序并标识必要的注释。保证程序能正确编译和运行,认真填写实验报告。
2.2 通过访问学生课程数据库中的表,设计数据库中函数,并编写嵌入式程序,完成下面功能:
1) 查询某一门课程的信息。要查询的课程由用户在程序运行过程中指定,放在主变量中。
2) 查询选修某一门课程的选课信息,要查询的课程号由用户在程序运行过程中指定,放在主变量中,然后根据用户的要求修改其中某些记录的成绩字段。
要求:提交源程序并标识必要的注释。保证程序能正确编译和运行,认真填写实验报告。
2.3 在高级语言中操作数据库
1)在高级语言中连接并操作访问MySQL数据库;
2)在高级语言中调用示例存储过程,并检查存储过程的效果;
3)在高级语言中调用函数,并检查函数的效果。
创建学生-课程数据库
#创建学生表
CREATE TABLE student (
sno CHAR(9) PRIMARY KEY, #列级完整性约束条件,sno是主码
sname VARCHAR(10) UNIQUE,
ssex CHAR(2),
sage SMALLINT,
sdept VARCHAR(20)
);
#创建课程表
CREATE TABLE course (
cno CHAR(4) PRIMARY KEY,
cname CHAR(40) NOT NULL,
cpno CHAR(4),
ccredit SMALLINT
);
#创建学生选课表
CREATE TABLE sc (
sno CHAR(9),
cno CHAR(4),
grade SMALLINT,
PRIMARY KEY (sno,cno),
FOREIGN KEY (sno) REFERENCES student (sno),
FOREIGN KEY (cno) REFERENCES course (cno)
);
#插入数据
INSERT INTO student
VALUES
('201215121', '李勇', '男', 20, 'CS'),
('201215122', '刘晨', '女', 19, 'CS'),
('201215123', '王敏', '女', 18, 'MA'),
('201215125', '张立', '男', 19, 'IS');
INSERT INTO course
VALUES
('1', '数据库', '5', 4),
('2', '数学', '', 2),
('3', '信息系统', '1', 4),
('4', '操作系统', '6', 3),
('5', '数据结构', '7', 4),
('6', '数据处理', '', 2),
('7', 'PASCAL语言', '6', 4),
#新增的数据
('8', '离散数学', '', 4);
INSERT INTO sc
VALUES
('201215121', '1', 92),
('201215121', '2', 85),
('201215121', '3', 88),
('201215122', '2', 90),
('201215122', '3', 80),
#新增的数据
('201215122', '8', 80),
('201215123', '8', 90);
2.1 对学生课程数据库,编写存储过程,完成下面功能:
1)统计离散数学的成绩分布情况,即按照各分数段统计人数;
DROP PROCEDURE IF EXISTS result1;
DELIMITER $$
CREATE
PROCEDURE `student`.`result1`(IN grade_start SMALLINT, IN grade_end SMALLINT, OUT result INT)
BEGIN
SELECT COUNT(*) FROM sc
LEFT OUTER JOIN course
ON sc.cno=course.cno
WHERE course.cname='离散数学'
AND sc.grade BETWEEN grade_start AND grade_end;
END$$
DELIMITER ;
2)统计任意一门课的平均成绩。
DROP PROCEDURE IF EXISTS result2;
DELIMITER $$
CREATE
PROCEDURE `student`.`result2`(IN cname CHAR(40),OUT result INT)
BEGIN
SELECT AVG(grade) FROM sc
WHERE cno=(
SELECT DISTINCT cno FROM course
WHERE course.cname=cname
);
END$$
DELIMITER ;
8号为离散数学,( 80 + 90 )/ 2 = 85
3)将学生选课成绩从百分制改为等级制(即A、B、C、D、E);
要求:提交源程序并标识必要的注释。保证程序能正确编译和运行,认真填写实验报告。
/*先给sc表添加一个字段grade_level,方便存储过程添加ABCDE*/
ALTER TABLE sc ADD grade_level CHAR(2);
DROP PROCEDURE IF EXISTS result3;
DELIMITER $$
CREATE
PROCEDURE `student`.`result3`()
BEGIN
UPDATE sc SET grade_level = 'A' WHERE grade BETWEEN 90 AND 100;
UPDATE sc SET grade_level = 'B' WHERE grade BETWEEN 80 AND 90;
UPDATE sc SET grade_level = 'C' WHERE grade BETWEEN 70 AND 80;
UPDATE sc SET grade_level = 'D' WHERE grade BETWEEN 60 AND 70;
UPDATE sc SET grade_level = 'E' WHERE grade BETWEEN 0 AND 60;
END$$
DELIMITER ;
CALL result3();
2.2 通过访问学生课程数据库中的表,设计数据库中函数,并编写嵌入式程序,完成下面功能:
1) 查询某一门课程的信息。要查询的课程由用户在程序运行过程中指定,放在主变量中。
/*这是我们开启了bin-log, 我们就必须指定我们的函数是否是
1 DETERMINISTIC 确定性的
2 NO SQL 没有SQl语句,当然也不会修改数据
3 READS SQL DATA 只是读取数据,当然也不会修改数据
4 MODIFIES SQL DATA 要修改数据
5 CONTAINS SQL 包含了SQL语句
其中在function里面,只有 DETERMINISTIC, NO SQL 和 READS SQL DATA 被支持。如果我们开启了 bin-log, 我们就必须为我们的function指定一个参数。
在MySQL中创建函数时出现这种错误的解决方法:
set global log_bin_trust_function_creators=TRUE; */
SET GLOBAL log_bin_trust_function_creators=TRUE;
DROP FUNCTION IF EXISTS function1;
DELIMITER $$
CREATE
FUNCTION `student`.`function1`(cno_show CHAR(4))
RETURNS VARCHAR(100)
BEGIN
DECLARE cname_show CHAR(40);
DECLARE cpno_show CHAR(4);
DECLARE ccredit_show SMALLINT;
SELECT cname INTO cname_show FROM course WHERE cno = cno_show;
SELECT cpno INTO cpno_show FROM course WHERE cno = cno_show;
SELECT ccredit INTO ccredit_show FROM course WHERE cno = cno_show;
#第一个参数为分隔符
RETURN CONCAT_WS('|', cno_show, cname_show, cpno_show, ccredit_show);
END$$
DELIMITER ;
#调用函数
SELECT function1('1') AS result;
2) 查询选修某一门课程的选课信息,要查询的课程号由用户在程序运行过程中指定,放在主变量中,然后根据用户的要求修改其中某些记录的成绩字段。
#解决报错的信息
SET GLOBAL log_bin_trust_function_creators=TRUE;
DROP FUNCTION IF EXISTS function2;
DELIMITER $$
CREATE
FUNCTION `student`.`function2`(
cno_show CHAR(4), cname_modify CHAR(40),
cpno_modify CHAR(4), ccredit_modify SMALLINT
)
RETURNS VARCHAR(100)
BEGIN
DECLARE cname_show CHAR(40);
DECLARE cpno_show CHAR(4);
DECLARE ccredit_show SMALLINT;
#按照要求修改数据
UPDATE course SET cname = cname_modify,
cpno = cpno_modify,
ccredit = ccredit_modify
WHERE cno = cno_show;
#赋值并将其返回
SELECT cname INTO cname_show FROM course WHERE cno = cno_show;
SELECT cpno INTO cpno_show FROM course WHERE cno = cno_show;
SELECT ccredit INTO ccredit_show FROM course WHERE cno = cno_show;
#第一个参数为分隔符
RETURN CONCAT_WS('|', cno_show, cname_show, cpno_show, ccredit_show);
END$$
DELIMITER ;
#调用函数
SELECT function2('1', '数据库2', '6', 5);
2.3 在高级语言中操作数据库
1)在高级语言中连接并操作访问MySQL数据库;
2)在高级语言中调用示例存储过程,并检查存储过程的效果;
3)在高级语言中调用函数,并检查函数的效果。
MySQL版本:8.0.20
使用Java JDBC进行连接
数据库连接字符串
serverTimezone=GMT%2B8 设置时区
useSSL=false 显式禁用SSL
String url = “jdbc:mysql:///student?serverTimezone=GMT%2B8&useSSL=false&nullCatalogMeansCurrent=true”;
package cn.edu.Gelcon;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
/**
* 2021年6月6日
*/
public class ConnectTest{
/**
* 关闭Connection
* @param conn
*/
public void close(Connection conn) {
if (conn != null) {
try {
conn.close();
System.out.println("ConnectEmp.close():Connection对象已关闭");
} catch (SQLException e) {
System.out.println("Connect关闭出现异常...");
e.printStackTrace();
}
}
}
/**
* 连接数据库
* @return Connection对象
*/
public Connection getConnect() {
Connection conn = null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
System.out.println("驱动加载成功");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
System.out.println("加载驱动失败");
// e.printStackTrace();
}
String url = "jdbc:mysql:///student?serverTimezone=GMT%2B8&useSSL=false&nullCatalogMeansCurrent=true";
try {
conn = DriverManager.getConnection(url, "root", "123456");
System.out.println("Connect.getConnect():" + "数据库连接成功");
} catch (SQLException e) {
// TODO Auto-generated catch block
System.out.println("连接数据库失败...");
// e.printStackTrace();
}
return conn;
}
public static void main(String[] args) {
ConnectTest p = new ConnectTest();
//连接数据库
Connection conn = p.getConnect();
//存储过程
p.callPro(conn);
//存储函数
p.callFun(conn);
}
public ConnectTest() {
}
/**
* 返回多个结果:
* 1. 返回查询所得的满足条件的所有行;
* 2. 返回存储过程的调用参数为输出类型的参数值
*/
public void callPro(Connection conn) {
//调用存储过程result2
String storedProc = "{call result2(?,?)}";
CallableStatement cs = null;
try {
cs = conn.prepareCall(storedProc);
// 第1个参数
cs.setString(1, "离散数学");
// 第2个为输出参数的类型
cs.registerOutParameter(2, Types.INTEGER);
// 执行存储过程
ResultSet rs = cs.executeQuery();
// cs.getString(2)表示第2个位置参数返回所对应的结果
//System.out.println("返回记录数:" + cs.getString(2));
int cnt = rs.getMetaData().getColumnCount();
// 最多返回一条记录,只需用if
if (rs.next()) {
// 获取查询所得的列数从1开始
Map<String, Object> obj = new HashMap<>();
for (int i = 1; i <= cnt; i++) {
// 获取列名
String columns = rs.getMetaData().getColumnName(i);
obj.put(columns, rs.getString(i));
}
// 遍历map
obj.forEach((k, v) -> {
System.out.println("Connect.callPro():" + k + "\\t" + v);
});
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 使用Connection对象的prepareCall方法调用存储函数 ,计算两个数所在区间上的所有数之和
*
*/
public void callFun(Connection conn) {
CallableStatement cs = null;
try {
cs = conn.prepareCall("{?=call function1(?)}");
cs.setString(2, "1");
cs.registerOutParameter(1, Types.VARCHAR);
cs.execute();
String res = cs.getString(1);
System.out.println("Connect.funAdd():\\t" + res);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
以上是关于2021-06-09的主要内容,如果未能解决你的问题,请参考以下文章