

逐题详细解析
第1题:添加外键约束
ALTER TABLE tb_course
ADD CONSTRAINT fk_tb_teacher
FOREIGN KEY (t_id) REFERENCES tb_teacher(t_id);
解析:
ALTER TABLE tb_course:修改课程表ADD CONSTRAINT fk_tb_teacher:添加名为fk_tb_teacher的约束FOREIGN KEY (t_id):指定本表的t_id字段为外键REFERENCES tb_teacher(t_id):引用教师表的t_id字段
注意事项:
- 确保
tb_teacher表中的t_id是主键或唯一键 - 确保两个表的
t_id字段数据类型一致
第2题:添加成绩记录
INSERT INTO tb_score (s_id, c_id, s_score)
VALUES ('07', '01', 90);
解析:
INSERT INTO tb_score:插入成绩表(s_id, c_id, s_score):指定要插入的字段VALUES ('07', '01', 90):对应的值
简化写法:
INSERT INTO tb_score VALUES ('07', '01', 90);
注意事项:
- 字符型数据加引号,数字可不加
- 确保学号
'07'在学生表中存在 - 确保课程号
'01'在课程表中存在
第3题:统计男生和女生人数
SELECT s_sex AS 性别, COUNT(*) AS 人数
FROM tb_student
GROUP BY s_sex;
解析:
SELECT s_sex AS 性别:输出性别,别名“性别”COUNT(*) AS 人数:统计人数,别名“人数”GROUP BY s_sex:按性别分组
输出示例:
| 性别 | 人数 |
|---|---|
| 男 | 25 |
| 女 | 23 |
保存:将语句保存到 sj13.txt 文件
第4题:查询不及格学生
SELECT s.s_name AS 学生姓名, sc.s_score AS 分数
FROM tb_student s
INNER JOIN tb_score sc ON s.s_id = sc.s_id
INNER JOIN tb_course c ON sc.c_id = c.c_id
WHERE c.c_name = 'PHP程序设计' AND sc.s_score < 60;
解析:
- 三表连接:学生表 → 成绩表 → 课程表
INNER JOIN:获取有成绩记录的学生WHERE c.c_name = 'PHP程序设计':筛选课程名AND sc.s_score < 60:筛选不及格(低于60分)
使用表别名简化:
SELECT s.s_name, sc.s_score
FROM tb_student s, tb_score sc, tb_course c
WHERE s.s_id = sc.s_id
AND sc.c_id = c.c_id
AND c.c_name = 'PHP程序设计'
AND sc.s_score < 60;
保存:将语句保存到 sj14.txt 文件
第5题:创建用户并授权
-- 创建用户
CREATE USER 'wang'@'localhost' IDENTIFIED BY 'password';
-- 授予权限(列级权限)
GRANT SELECT (s_score)
ON db_grade.tb_score
TO 'wang'@'localhost';
解析:
创建用户部分:
CREATE USER:创建新用户'wang'@'localhost':用户名和主机名IDENTIFIED BY 'password':设置密码(可自行设置)
授权部分:
GRANT SELECT (s_score):只授予查询s_score字段的权限ON db_grade.tb_score:指定数据库和表TO 'wang'@'localhost':指定用户
简化写法(授予整个表权限):
GRANT SELECT ON db_grade.tb_score TO 'wang'@'localhost';
答案汇总
| 题号 | 答案 |
|---|---|
| 1 | ALTER TABLE tb_course ADD CONSTRAINT fk_tb_teacher FOREIGN KEY (t_id) REFERENCES tb_teacher(t_id); |
| 2 | INSERT INTO tb_score (s_id, c_id, s_score) VALUES ('07', '01', 90); |
| 3 | SELECT s_sex AS 性别, COUNT(*) AS 人数 FROM tb_student GROUP BY s_sex; |
| 4 | SELECT s.s_name AS 学生姓名, sc.s_score AS 分数 FROM tb_student s INNER JOIN tb_score sc ON s.s_id = sc.s_id INNER JOIN tb_course c ON sc.c_id = c.c_id WHERE c.c_name = 'PHP程序设计' AND sc.s_score < 60; |
| 5 | CREATE USER 'wang'@'localhost' IDENTIFIED BY 'password';GRANT SELECT (s_score) ON db_grade.tb_score TO 'wang'@'localhost'; |
知识点总结
| 题号 | 考点 | 关键语法 |
|---|---|---|
| 1 | 外键约束 | ALTER TABLE ... ADD CONSTRAINT ... FOREIGN KEY ... REFERENCES |
| 2 | 插入数据 | INSERT INTO ... VALUES |
| 3 | 分组统计 | GROUP BY + COUNT(*) |
| 4 | 多表连接查询 | INNER JOIN + WHERE |
| 5 | 创建用户+列级授权 | CREATE USER + GRANT SELECT(字段) |

USE db_grade;
DELIMITER $$
CREATE PROCEDURE sp_count(IN SEX VARCHAR(20), OUT ROWS INT)
BEGIN
DECLARE sno VARCHAR(20);
DECLARE FOUND BOOLEAN DEFAULT TRUE;
DECLARE cur_cno ________ FOR
SELECT s_id FROM tb_student WHERE s_sex = SEX AND s_birth ________ "1993%";
DECLARE CONTINUE HANDLER FOR NOT FOUND
SET FOUND=FALSE;
SET ________ = 0;
OPEN cur_cno;
FETCH cur_cno INTO sno;
WHILE FOUND DO
________ ROWS=ROWS+1;
FETCH cur_cno INTO sno;
END WHILE;
________ cur_cno;
END $$
存储过程 sp_count 逐空详细解析
第1个空:CURSOR
DECLARE cur_cno ________ FOR
答案:CURSOR
解析:
- 声明游标的关键字
- 语法:
DECLARE 游标名 CURSOR FOR SELECT语句 cur_cno是游标名称,用于遍历查询结果集
第2个空:LIKE
WHERE s_sex = SEX AND s_birth ________ "1993%"
答案:LIKE
解析:
- 模式匹配操作符
LIKE "1993%"匹配所有以 “1993” 开头的出生日期- 出生日期格式为
YYYY-MM-DD(如1993-05-20),"1993%"能匹配所有1993年出生的学生
其他写法:
YEAR(s_birth) = 1993也可以,但本题用LIKE
第3个空:ROWS
SET ________ = 0;
答案:ROWS
解析:
ROWS是存储过程的输出参数(OUT ROWS INT)- 初始化为0,然后每找到一条符合条件的记录就加1
第4个空:SET
________ ROWS = ROWS + 1;
答案:SET
解析:
- 赋值语句的关键字
- 语法:
SET 变量 = 表达式 - 每读取一行,计数器加1
第5个空:CLOSE
________ cur_cno;
答案:CLOSE
解析:
- 关闭游标的关键字
- 游标使用完毕后必须关闭,释放资源
- 语法:
CLOSE 游标名
完整代码
USE db_grade;
DELIMITER $$
CREATE PROCEDURE sp_count(IN SEX VARCHAR(20), OUT ROWS INT)
BEGIN
DECLARE sno VARCHAR(20);
DECLARE FOUND BOOLEAN DEFAULT TRUE;
DECLARE cur_cno CURSOR FOR
SELECT s_id FROM tb_student WHERE s_sex = SEX AND s_birth LIKE "1993%";
DECLARE CONTINUE HANDLER FOR NOT FOUND
SET FOUND=FALSE;
SET ROWS = 0;
OPEN cur_cno;
FETCH cur_cno INTO sno;
WHILE FOUND DO
SET ROWS = ROWS + 1;
FETCH cur_cno INTO sno;
END WHILE;
CLOSE cur_cno;
END $$
DELIMITER ;
存储过程功能说明
功能:统计指定性别在1993年出生的学生人数
执行逻辑:
1. 接收输入参数 SEX(性别)
2. 声明游标,查询符合条件的学号
3. 初始化 ROWS = 0
4. 打开游标,循环读取每一行
5. 每读一行,ROWS 加 1
6. 读取完毕,关闭游标
7. 返回 ROWS(人数)
调用示例:
-- 统计1993年出生的女生人数
CALL sp_count('女', @count);
SELECT @count;
-- 统计1993年出生的男生人数
CALL sp_count('男', @count);
SELECT @count;
答案汇总
| 空位 | 答案 | 含义 |
|---|---|---|
| 第1空 | CURSOR | 声明游标关键字 |
| 第2空 | LIKE | 模式匹配操作符 |
| 第3空 | ROWS | 输出参数名 |
| 第4空 | SET | 赋值语句关键字 |
| 第5空 | CLOSE | 关闭游标关键字 |
DELIMITER $$
CREATE ________ fn_search_name(stu_id VARCHAR(20))
________ VARCHAR(20)
DETERMINISTIC
BEGIN
DECLARE stu_name VARCHAR(20);
SELECT s_name INTO stu_name FROM ________ WHERE s_id = stu_id;
IF ________ IS NULL THEN
RETURN(SELECT '没有这名学生');
ELSE RETURN(SELECT stu_name);
END ________;
END$$
DELIMITER ;
函数 fn_search_name 逐空详细解析
第1个空:FUNCTION
CREATE ________ fn_search_name(stu_id VARCHAR(20))
答案:FUNCTION
解析:
- 创建函数的关键字
- 语法:
CREATE FUNCTION 函数名(参数列表) - 与存储过程
CREATE PROCEDURE区分
第2个空:RETURNS
________ VARCHAR(20)
答案:RETURNS
解析:
- 声明函数返回类型的关键字
- 语法:
RETURNS 数据类型 - 这里返回
VARCHAR(20)类型的学生姓名
注意:是 RETURNS(带S),不是 RETURN
第3个空:tb_student
SELECT s_name INTO stu_name FROM ________ WHERE s_id = stu_id;
答案:tb_student
解析:
- 学生表的表名
- 根据学号
s_id查询学生姓名s_name - 查询结果存入变量
stu_name
第4个空:stu_name
IF ________ IS NULL THEN
答案:stu_name
解析:
- 判断查询结果是否为空
stu_name是之前声明的变量,存储查询到的学生姓名- 如果
stu_name为NULL,说明学号不存在
第5个空:IF
END ________;
答案:IF
解析:
- 结束
IF语句的关键字 - 语法:
END IF; - 与开头的
IF配对
完整代码
DELIMITER $$
CREATE FUNCTION fn_search_name(stu_id VARCHAR(20))
RETURNS VARCHAR(20)
DETERMINISTIC
BEGIN
DECLARE stu_name VARCHAR(20);
SELECT s_name INTO stu_name FROM tb_student WHERE s_id = stu_id;
IF stu_name IS NULL THEN
RETURN(SELECT '没有这名学生');
ELSE RETURN(SELECT stu_name);
END IF;
END$$
DELIMITER ;
函数功能说明
功能:根据学号查询学生姓名
执行逻辑:
1. 接收输入参数 stu_id(学号)
2. 声明变量 stu_name(存储学生姓名)
3. 根据学号查询学生姓名存入 stu_name
4. 判断 stu_name 是否为 NULL
├─ 是 → 返回 '没有这名学生'
└─ 否 → 返回 stu_name(学生姓名)
调用示例:
-- 查询学号 001 的学生姓名
SELECT fn_search_name('001');
-- 查询不存在的学号
SELECT fn_search_name('999'); -- 返回 '没有这名学生'
-- 在查询中使用
SELECT s_id, fn_search_name(s_id) AS 姓名 FROM tb_student;
答案汇总
| 空位 | 答案 | 含义 |
|---|---|---|
| 第1空 | FUNCTION | 创建函数关键字 |
| 第2空 | RETURNS | 返回类型声明 |
| 第3空 | tb_student | 学生表名 |
| 第4空 | stu_name | 变量名 |
| 第5空 | IF | 结束IF语句 |
<?php
$host="localhost"; $user="root"; $pwd="";
$db_name="db_grade";
$conn=mysql_connect($host,$user,$pwd)
or die("连接数据库服务器失败...");
//**********found**********
mysql_select_db($db_name,_____________)
or die("连接数据库失败...");
mysql_query("set names 'gbk'");
?>
<html>
<head><title>选修了三门及以上课程的学生名单</title></head>
<body>
<?php
//**********found**********
$cmd="SELECT s.s_id, s.s_name FROM tb_score sc _____________ tb_student s ON sc.s_id = s.s_id GROUP BY s.s_id HAVING COUNT(*) >= 3";
$result=mysql_query($cmd,$conn);
if($result){
//**********found**********
printf("共有 %s 名学生至少选修了三门课程\n", _____________($result));
}
print "<table width=280 border=1 align=center>";
print "<caption>选修三门及以上课程的学生名单</caption>";
print "<tr><td>学号</td><td>姓名</td></tr>";
//**********found**********
while($row=mysql_fetch_array(_____________)){
print "<tr><td>$row[0]</td><td>$row[1]</td></tr>";
}
print "</table><br><br>"
?>
</body>
</html>
PHP程序逐空详细解析
第1个空:$conn
mysql_select_db($db_name,_____________)
答案:$conn
解析:
mysql_select_db()的第二个参数是数据库连接资源- 前面
mysql_connect()返回的连接资源存储在$conn变量中 - 需要传入
$conn才能正确选择数据库
第2个空:JOIN
$cmd="SELECT s.s_id, s.s_name FROM tb_score sc _____________ tb_student s ON sc.s_id = s.s_id GROUP BY s.s_id HAVING COUNT(*) >= 3";
答案:JOIN
解析:
- 连接学生表和成绩表的关键字
- 语法:
表1 JOIN 表2 ON 连接条件 - 这里用
JOIN(或INNER JOIN)连接两表
完整SQL:
SELECT s.s_id, s.s_name
FROM tb_score sc
JOIN tb_student s ON sc.s_id = s.s_id
GROUP BY s.s_id
HAVING COUNT(*) >= 3
第3个空:mysql_num_rows
printf("共有 %s 名学生至少选修了三门课程\n", _____________($result));
答案:mysql_num_rows
解析:
- 获取结果集中记录行数的函数
- 语法:
mysql_num_rows(结果集资源) - 返回满足条件的学生人数(选修三门及以上)
第4个空:$result
while($row=mysql_fetch_array(_____________)){
答案:$result
解析:
mysql_fetch_array()需要传入结果集资源- 前面
$result=mysql_query($cmd,$conn)执行查询返回结果集 - 需要将
$result作为参数传入
完整代码
<?php
$host="localhost"; $user="root"; $pwd="";
$db_name="db_grade";
$conn=mysql_connect($host,$user,$pwd)
or die("连接数据库服务器失败...");
//**********found**********
mysql_select_db($db_name,$conn)
or die("连接数据库失败...");
mysql_query("set names 'gbk'");
?>
<html>
<head><title>选修了三门及以上课程的学生名单</title></head>
<body>
<?php
//**********found**********
$cmd="SELECT s.s_id, s.s_name FROM tb_score sc JOIN tb_student s ON sc.s_id = s.s_id GROUP BY s.s_id HAVING COUNT(*) >= 3";
$result=mysql_query($cmd,$conn);
if($result){
//**********found**********
printf("共有 %s 名学生至少选修了三门课程\n", mysql_num_rows($result));
}
print "<table width=280 border=1 align=center>";
print "<caption>选修三门及以上课程的学生名单</caption>";
print " <tr><th>学号</th><th>姓名</th></tr>";
//**********found**********
while($row=mysql_fetch_array($result)){
print " <tr><td>$row[0]</td><td>$row[1]</td></tr>";
}
print "</table><br><br>"
?>
</body>
</html>
程序功能说明
功能:查询选修了三门及以上课程的学生名单
执行流程:
1. 连接数据库 db_grade
2. 执行SQL查询:
- 连接成绩表(tb_score)和学生表(tb_student)
- 按学号分组
- 筛选选修课程数 ≥ 3 的学生
3. 输出学生总数
4. 输出学生名单(学号、姓名)
SQL语句解析
SELECT s.s_id, s.s_name
FROM tb_score sc
JOIN tb_student s ON sc.s_id = s.s_id
GROUP BY s.s_id
HAVING COUNT(*) >= 3
| 部分 | 作用 |
|---|---|
FROM tb_score sc | 成绩表(主表) |
JOIN tb_student s | 连接学生表 |
ON sc.s_id = s.s_id | 连接条件 |
GROUP BY s.s_id | 按学号分组 |
HAVING COUNT(*) >= 3 | 筛选选修课程数≥3 |
答案汇总
| 空位 | 答案 | 说明 |
|---|---|---|
| 第1空 | $conn | 数据库连接资源 |
| 第2空 | JOIN | 表连接关键字 |
| 第3空 | mysql_num_rows | 获取结果集行数函数 |
| 第4空 | $result | 结果集资源 |
发表回复