《数据库系统概论》课程之实验五
通过嵌入式SQL访问数据库
1实验目的
熟悉通过嵌入式SQL(主语言为C语言)编程访问数据库。
实验以C语言为例作说明,实作可以选择任意语言实现本实验。
2实验平台和实验工具
在KingbaseES数据库管理系统上,通过C语言编写访问数据库的应用程序来对数据库进行各种数据操作。编程工具自选。
3实验内容和要求
熟悉RDBMS的预编译程序。通过嵌入式SQL编程访问数据库的基本步骤
对学生课程数据库中的表,完成下面功能(你也可以自己给出功能要求):
《数据库系统概论》课程之实验六
使用PL/SQL编写存储过程访问数据库
对学生课程数据库,编写存储过程,完成下面功能:
1)统计离散数学的成绩分布情况,即按照各分数段统计人数;
2)统计任意一门课的平均成绩。
3)将学生选课成绩从百分制改为等级制(即A、B、C、D、E);
要求:提交源程序并标识必要的注释。保证程序能正确编译和运行,认真填写实验报告。
熟悉通过嵌入式SQL(主语言为C语言)编程访问数据库。
实验以C语言为例作说明,实作可以选择任意语言实现本实验。
查询某一门课程的信息。要查询的课程由用户在程序运行过程中指定,放在主变量中。
查询选修某一门课程的选课信息,要查询的课程号由用户在程序运行过程中指定,放在主变量中,然后根据用户的要求修改其中某些记录的成绩字段。
要求:提交源程序并标识必要的注释。保证程序能正确编译和运行,认真填写实验报告。
<properties>
<maven.compiler.source>8maven.compiler.source>
<maven.compiler.target>8maven.compiler.target>
properties>
<dependencies>
<dependency>
<groupId>com.mchangegroupId>
<artifactId>c3p0artifactId>
<version>0.9.5.5version>
dependency>
<dependency>
<groupId>com.mchangegroupId>
<artifactId>mchange-commons-javaartifactId>
<version>0.2.20version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.49version>
dependency>
dependencies>
处理静态资源过滤问题
<build>
<resources>
<resource>
<directory>src/main/javadirectory>
<includes>
<include>**/*.propertiesinclude>
<include>**/*.xmlinclude>
includes>
<filtering>falsefiltering>
resource>
<resource>
<directory>src/main/resourcesdirectory>
<includes>
<include>**/*.propertiesinclude>
<include>**/*.xmlinclude>
includes>
<filtering>falsefiltering>
resource>
resources>
build>
编写c3p0-config.xml配置文件
<c3p0-config>
<default-config>
<property name="driverClass">com.mysql.jdbc.Driverproperty>
<property name="jdbcUrl">jdbc:mysql://localhost/stdproperty>
<property name="user">rootproperty>
<property name="password">rootproperty>
<property name="initialPoolSize">10property>
<property name="maxIdleTime">30property>
<property name="maxPoolSize">100property>
<property name="minPoolSize">10property>
<property name="maxStatements">200property>
default-config>
<named-config name="MySQL">
<property name="driverClass">com.mysql.jdbc.Driverproperty>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/dblab?useSSL=false&useUnicode=true&characterEncoding=utf8property>
<property name="user">rootproperty>
<property name="password">123456property>
<property name="acquireIncrement">5property>
<property name="initialPoolSize">10property>
<property name="minPoolSize">5property>
<property name="maxPoolSize">20property>
named-config>
c3p0-config>
编写工具类
public class UtilsJDBC_C3P0 {
static DataSource dataSource =null;
static {
try {
//创建数据源 工厂模式
dataSource = new ComboPooledDataSource("MySQL");//配置文件写法
} catch (Exception e) {
e.printStackTrace();
}
}
//1.获取连接
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
//2.释放连接
public static void releaseConnection(Connection conn, Statement st, ResultSet res) {
try {
if(res!=null) res.close();
if(st!=null) st.close();
if(conn!=null) conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public void print() throws SQLException {
System.out.println("课程号\t\t\t\t课程名\t\t先行课\t\t学分");
while (res.next()){
String Cno=res.getObject("Cno")+"";
String Cname=res.getObject("Cname")+"";
String Cpno=res.getObject("Cpno")+" ";
String Ccredit=res.getObject("Ccredit")+"";
System.out.println(Cno+"\t\t\t\t\t"+Cname+"\t\t\t"+Cpno+"\t\t"+Ccredit);
}
System.out.println("=========================================================");
}
public void func01() throws SQLException {
conn = UtilsJDBC_C3P0.getConnection();
while (true) {
System.out.println("请选择查询:1.课程号 2.课程名 3.退出");
System.out.println("=========================================================");
Scanner in = new Scanner(System.in);
int order=in.nextInt();
System.out.println("=========================================================");
if(order==1){
System.out.print("请输入课程编号:");
String Cno=in.next();
String sql = "SELECT * FROM `course` WHERE `Cno`=?";
st = conn.prepareStatement(sql);//预编译sql,先写sql,不执行
st.setString(1,Cno);
res = st.executeQuery();
print();
}else if(order==2){
System.out.print("请输入课程名:");
String Cname=in.next();
String sql = "SELECT * FROM `course` WHERE `Cname`=?";
st = conn.prepareStatement(sql);//预编译sql,先写sql,不执行
st.setString(1,Cname);
res = st.executeQuery();
print();
}else if(order==3){
break;
}else{
System.out.println("输入错误!");
}
}
UtilsJDBC_C3P0.releaseConnection(conn, st, res);
}
public void print02() throws SQLException {
System.out.println("学号\t\t\t\t名字\t\t成绩\t\t院系");
while (res.next()){
String Sno=res.getObject("Sno")+"";
String Sname=res.getObject("Sname")+"";
String Grade=res.getObject("Grade")+" ";
String Sdept=res.getObject("Sdept")+"";
System.out.println(Sno+"\t\t"+Sname+"\t\t"+Grade+"\t"+Sdept);
}
System.out.println("=========================================================");
}
// System.out.println("201215121\t\t刘晨\t\t80\t\tCS");
//2. 查询选修某一门课程的选课信息,要查询的课程号由用户在程序运行过程中指定,放在主变量中,
//3. 然后根据用户的要求修改其中某些记录的成绩字段。
public void func02() throws SQLException {
conn = UtilsJDBC_C3P0.getConnection();
while (true) {
System.out.println("请选择服务: 1.查询课程信息 2.退出");
System.out.println("=========================================================");
Scanner in = new Scanner(System.in);
int order=in.nextInt();
if(order==1){
System.out.print("请输入课程编号:");
String Cno=in.next();
String sql = "SELECT stc.Sno , `Sname`, `Grade` ,`Sdept`\n" +
"FROM `sc` stc\n" +
"INNER JOIN `student` stu\n" +
"WHERE stc.Sno=stu.`Sno` AND `Cno`=?";
st = conn.prepareStatement(sql);//预编译sql,先写sql,不执行
st.setString(1,Cno);
res = st.executeQuery();
print02();
while (true){
System.out.print("是否修改学生成绩 Y/N: ");
String modify=in.next();
if(modify.equals("Y")){
System.out.print("输入学生名字:");
String Sname=in.next();
System.out.print("输入修改成绩:");
float Grade=in.nextFloat();
String sqlM="UPDATE `sc` SET `Grade`=? WHERE `Cno`=? AND `Sno`=(\n" +
" SELECT `Sno` FROM `student` WHERE `Sname`=?\n" +
")";
st = conn.prepareStatement(sqlM);
st.setFloat(1,Grade);
st.setString(2,Cno);
st.setString(3,Sname);
int i = st.executeUpdate();
if(i>0) System.out.println("更新成功");
else System.out.println("更新失败");
}else if(modify.equals("N")){
break;
}else {
System.out.println("输入错误!");
}
}
}else if(order==2){
break;
}else{
System.out.println("输入错误!");
}
}
UtilsJDBC_C3P0.releaseConnection(conn, st, res);
}
制表符规则
/t的对齐规则为:
向/t前字符长度为n的字符串补足成8的整数倍(当然可以设置补足成其他的倍数)。比如:
n=1,补足的空格长度为7。
n=7, 补足的空格长度为1。
n=9,补足的空格长度为7。
注意:
n为8的整数倍时,补足长度为8。比如
n=8,补足长度为8。
熟悉使用存储过程来进行数据库应用程序的设计。
对学生课程数据库,编写存储过程,完成下面功能
1)统计离散数学的成绩分布情况,即按照各分数段统计人数;
因为存储过程执行后在客户端并没有返回值,因此需要建立一个表来存放执行后的结果,并返回客户端显示。
根据实验要求,要统计选修“离散数学”课程的学生的成绩分布,因此需要建立rank。
CREATE TABLE `rank`
(
`division` CHAR(20),
`number` INT
)ENGINE=INNODB DEFAULT CHARSET=utf8;
TRUNCATE `rank`;
编写存储过程
DELIMITER $$
CREATE PROCEDURE statistic_mark(CourseName CHAR(30))
BEGIN
DECLARE less60 INT DEFAULT 0;
DECLARE b60a70 INT DEFAULT 0;
DECLARE b70a80 INT DEFAULT 0;
DECLARE b80a90 INT DEFAULT 0;
DECLARE more90 INT DEFAULT 0;
DECLARE currCno CHAR(4);
SELECT `Cno` INTO currCno FROM `course` WHERE `Cname`=CourseName;
SELECT COUNT(*) INTO less60 FROM `sc` WHERE `Cno` =currCno AND `Grade`<60;
SELECT COUNT(*) INTO b60a70 FROM `sc` WHERE `Cno` =currCno AND `Grade`>=60 AND `Grade`<70;
SELECT COUNT(*) INTO b70a80 FROM `sc` WHERE `Cno` =currCno AND `Grade`>=70 AND `Grade`<80;
SELECT COUNT(*) INTO b80a90 FROM `sc` WHERE `Cno` =currCno AND `Grade`>=80 AND `Grade`<90;
SELECT COUNT(*) INTO more90 FROM `sc` WHERE `Cno` =currCno AND `Grade`>=90 ;
INSERT INTO `rank`(`division`,`number`) VALUES ('[0,60)',less60);
INSERT INTO `rank`(`division`,`number`) VALUES ('[60,70)',b60a70);
INSERT INTO `rank`(`division`,`number`) VALUES ('[70,80)',b70a80);
INSERT INTO `rank`(`division`,`number`) VALUES ('[80,90)',b80a90);
INSERT INTO `rank`(`division`,`number`) VALUES ('[90,100)',more90);
END $$
DROP PROCEDURE statistic_mark;
CALL statistic_mark('离散数学');
执行结果:
2)统计任意一门课的平均成绩。
创建需要的表结构:
DROP TABLE IF EXISTS `avgGrade`;
CREATE TABLE `avgGrade`
(
`Cname` CHAR(20),
`CAvg` NUMERIC(10,6)
)ENGINE =INNODB DEFAULT CHARSET =utf8;
创建存储过程
DELIMITER $$
CREATE PROCEDURE statistic_avg()
BEGIN
DECLARE currName CHAR(20);
DECLARE currCno CHAR(9);
DECLARE currAvg NUMERIC(10,6);
DECLARE done INT DEFAULT 0;
-- 声明不带参数的游标myCursor查询课程号和课程名称
DECLARE myCursor CURSOR FOR SELECT `Cno`,`Cname` FROM `course`;
-- 捕获系统抛出的 not found 错误,如果捕获到,将 done 设置为 1 相当于try异常
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1;
OPEN myCursor;
www:LOOP
-- 游标推进一行取结果赋值给变量
FETCH myCursor INTO currCno,currName;
-- 如果没有返回值,则退出循环
IF done=1 THEN
LEAVE www;
END IF;
SELECT AVG(`Grade`) INTO currAvg FROM `sc` WHERE `Cno`=currCno;
INSERT INTO `avgGrade`(`Cname`,`CAvg`) VALUES (currName,currAvg);
END LOOP;
CLOSE myCursor;
END $$
DELETE FROM `avgGrade`;
CALL statistic_avg();
DROP PROCEDURE statistic_avg;
执行结果:
3)将学生选课成绩从百分制改为等级制(即A、B、C、D、E);
创建所需表:由于代码赋值时报错所以采取该种方式进行赋值。
DROP TABLE IF EXISTS `changeGrade`;
CREATE TABLE `changeGrade`
(
num INT,
cGrade CHAR(2)
)ENGINE =INNODB DEFAULT CHARSET =utf8;
ALTER TABLE `sc` ADD newGrade CHAR(2);
创建存储过程
DROP PROCEDURE IF EXISTS statistic_change;
DELIMITER $$
CREATE PROCEDURE statistic_change()
BEGIN
DECLARE chGrade CHAR(2);
DECLARE currSno CHAR(9);
DECLARE currCno CHAR(9);
DECLARE currGrade FLOAT;
DECLARE done INT DEFAULT 0;
-- 声明不带参数的游标myCursor查询课程号和课程名称
DECLARE myCursor CURSOR FOR SELECT `Sno`,`Cno`,`Grade` FROM `sc`;
-- 捕获系统抛出的 not found 错误,如果捕获到,将 done 设置为 1 相当于try异常
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1;
OPEN myCursor;
www:LOOP
-- 游标推进一行取结果赋值给变量
FETCH myCursor INTO currSno,currCno,currGrade;
-- 如果没有返回值,则退出循环
IF done=1 THEN
LEAVE www;
END IF;
IF currGrade<60 THEN
SELECT `cGrade` INTO chGrade FROM `changeGrade` WHERE `num`=1;
END IF;
IF currGrade>=60 AND currGrade<70 THEN
SELECT `cGrade` INTO chGrade FROM `changeGrade` WHERE `num`=2;
END IF;
IF currGrade>=70 AND currGrade<80 THEN
SELECT `cGrade` INTO chGrade FROM `changeGrade` WHERE `num`=3;
END IF;
IF currGrade>=80 AND currGrade<90 THEN
SELECT `cGrade` INTO chGrade FROM `changeGrade` WHERE `num`=4;
END IF;
IF currGrade>=90 AND currGrade<101 THEN
SELECT `cGrade` INTO chGrade FROM `changeGrade` WHERE `num`=5;
END IF;
UPDATE `sc` SET sc.`newGrade`=chGrade WHERE `Sno`=currSno AND `Cno`=currCno;
END LOOP;
CLOSE myCursor;
END $$
CALL statistic_change();