

逐题详细解析
第1题:修改字段类型
ALTER TABLE tb_class
MODIFY department VARCHAR(20);
解析:
ALTER TABLE tb_class:修改班级信息表MODIFY department:修改department字段VARCHAR(20):将数据类型改为变长字符串,长度20- 不能修改字段名称,所以用
MODIFY而不是CHANGE
注意:如果原字段有 NOT NULL 或 DEFAULT 约束,需要保留:
ALTER TABLE tb_class
MODIFY department VARCHAR(20) NOT NULL DEFAULT '';
第2题:更新班级所属院系
UPDATE tb_class
SET department = '管理学院'
WHERE classno LIKE '%信息管理%';
解析:
UPDATE tb_class:更新班级信息表SET department = '管理学院':将院系设置为“管理学院”WHERE classno LIKE '%信息管理%':班级编号中包含“信息管理”的班级
LIKE 通配符说明:
| 写法 | 含义 |
|---|---|
'%信息管理%' | 包含“信息管理” |
'信息管理%' | 以“信息管理”开头 |
'%信息管理' | 以“信息管理”结尾 |
第3题:查询参加社团总数排名前两位的学生
SELECT s.sno, s.sname, COUNT(gs.gno) AS 参加社团总数
FROM tb_student s
LEFT JOIN tb_gs gs ON s.sno = gs.sno
GROUP BY s.sno, s.sname
ORDER BY 参加社团总数 DESC
LIMIT 2;
解析:
LEFT JOIN:确保没有参加社团的学生也被统计(人数为0)GROUP BY:按学号分组,统计每个学生参加的社团数ORDER BY ... DESC:按社团总数降序排列LIMIT 2:取前两名
输出字段:学号、姓名、参加社团总数
保存:将语句保存到 sj13.txt 文件
第4题:创建视图
CREATE VIEW v_club AS
SELECT g.gname AS 社团名称, COUNT(gs.sno) AS 社团人数
FROM tb_group g
LEFT JOIN tb_gs gs ON g.gno = gs.gno
GROUP BY g.gno, g.gname
ORDER BY 社团人数 DESC;
解析:
CREATE VIEW v_club:创建名为v_club的视图AS 社团名称:字段别名显示为“社团名称”AS 社团人数:字段别名显示为“社团人数”LEFT JOIN:确保没有成员的社团也显示(人数为0)GROUP BY:按社团分组统计人数ORDER BY 社团人数 DESC:按人数降序排列
第5题:授予用户权限
GRANT UPDATE (sname)
ON db_club.tb_student
TO '李宏'@'localhost'
WITH GRANT OPTION;
解析:
GRANT UPDATE (sname):授予修改学生姓名的权限(列级权限)ON db_club.tb_student:指定数据库和表TO '李宏'@'localhost':指定用户和主机名WITH GRANT OPTION:允许该用户将权限传播给其他用户
如果用户不存在,先创建:
CREATE USER '李宏'@'localhost' IDENTIFIED BY 'password';
答案汇总
| 题号 | 答案 |
|---|---|
| 1 | ALTER TABLE tb_class MODIFY department VARCHAR(20); |
| 2 | UPDATE tb_class SET department = '管理学院' WHERE classno LIKE '%信息管理%'; |
| 3 | SELECT s.sno, s.sname, COUNT(gs.gno) AS 参加社团总数 FROM tb_student s LEFT JOIN tb_gs gs ON s.sno = gs.sno GROUP BY s.sno, s.sname ORDER BY 参加社团总数 DESC LIMIT 2; |
| 4 | CREATE VIEW v_club AS SELECT g.gname AS 社团名称, COUNT(gs.sno) AS 社团人数 FROM tb_group g LEFT JOIN tb_gs gs ON g.gno = gs.gno GROUP BY g.gno, g.gname ORDER BY 社团人数 DESC; |
| 5 | GRANT UPDATE (sname) ON db_club.tb_student TO '李宏'@'localhost' WITH GRANT OPTION; |
知识点总结
| 题号 | 考点 | 关键语法 |
|---|---|---|
| 1 | 修改字段类型 | ALTER TABLE ... MODIFY ... |
| 2 | 条件更新 | UPDATE ... SET ... WHERE ... LIKE |
| 3 | 分组统计+排序+限制 | GROUP BY + COUNT() + ORDER BY + LIMIT |
| 4 | 创建视图 | CREATE VIEW ... AS SELECT ... |
| 5 | 列级权限+传播 | GRANT UPDATE(字段) ... WITH GRANT OPTION |
DELIMITER $$
CREATE PROCEDURE sp_gs( ______ groupname VARCHAR(20))
BEGIN
DECLARE num TINYINT;
DECLARE years TINYINT;
SELECT _____________ INTO num FROM tb_gs, tb_group WHERE tb_gs.gno = tb_group.gno AND gname = groupname;
SELECT TIMESTAMPDIFF(YEAR,buildup,CURDATE()) INTO years FROM tb_group WHERE gname = groupname;
IF ( ____________ AND ____________ ) THEN
DELETE FROM tb_group WHERE gname = groupname;
END IF;
END $$
DELIMITER ;
存储过程 sp_gs 逐空详细解析
第1个空:IN
CREATE PROCEDURE sp_gs( ______ groupname VARCHAR(20))
答案:IN
解析:
- 存储过程的参数类型关键字
IN表示输入参数,由调用者传入groupname是社团名称,用于指定要操作的社团
第2个空:COUNT(*)
SELECT _____________ INTO num FROM tb_gs, tb_group WHERE tb_gs.gno = tb_group.gno AND gname = groupname;
答案:COUNT(*)
解析:
- 统计该社团的成员人数
num变量用于存储成员数量- 连接条件:
tb_gs.gno = tb_group.gno关联社团表和成员表
子查询逻辑:
SELECT COUNT(*) INTO num
FROM tb_gs, tb_group
WHERE tb_gs.gno = tb_group.gno AND gname = groupname;
-- 统计指定社团有多少成员
第3个空:num = 0
IF ( ____________ AND ____________ ) THEN
答案:num = 0
解析:
- 第一个条件:成员人数为0
- 即该社团没有任何成员
第4个空:years >= 3
IF ( num = 0 AND ____________ ) THEN
答案:years >= 3
解析:
- 第二个条件:社团成立年限大于等于3年
years变量存储的是成立年限(已通过TIMESTAMPDIFF计算)- 两个条件同时满足时,才执行删除操作
完整代码
DELIMITER $$
CREATE PROCEDURE sp_gs(IN groupname VARCHAR(20))
BEGIN
DECLARE num TINYINT;
DECLARE years TINYINT;
SELECT COUNT(*) INTO num FROM tb_gs, tb_group WHERE tb_gs.gno = tb_group.gno AND gname = groupname;
SELECT TIMESTAMPDIFF(YEAR, buildup, CURDATE()) INTO years FROM tb_group WHERE gname = groupname;
IF (num = 0 AND years >= 3) THEN
DELETE FROM tb_group WHERE gname = groupname;
END IF;
END $$
DELIMITER ;
存储过程功能说明
功能:删除符合条件的社团(无成员且成立满3年)
执行逻辑:
1. 接收输入参数 groupname(社团名称)
2. 统计该社团的成员人数 → num
3. 计算该社团成立至今的年数 → years
4. 判断条件:
- 成员人数为0(num = 0)
- 成立年限 ≥ 3年(years >= 3)
5. 两个条件都满足时,删除该社团
调用示例:
-- 删除“书法社”(如果无成员且成立满3年)
CALL sp_gs('书法社');
关键函数说明
TIMESTAMPDIFF 函数
TIMESTAMPDIFF(YEAR, buildup, CURDATE())
- 计算两个日期之间的差值
YEAR:以年为单位buildup:社团成立时间CURDATE():当前日期- 返回成立至今的年数
示例:
| 成立时间 | 当前日期 | 返回值 |
|---|---|---|
| 2020-03-01 | 2026-03-28 | 6 |
| 2024-12-01 | 2026-03-28 | 1 |
答案汇总
| 空位 | 答案 | 含义 |
|---|---|---|
| 第1空 | IN | 输入参数类型 |
| 第2空 | COUNT(*) | 统计成员人数 |
| 第3空 | num = 0 | 成员人数为0 |
| 第4空 | years >= 3 | 成立满3年 |
DELIMITER //
CREATE TRIGGER tr_gs BEFORE INSERT
ON tb_gs FOR EACH ROW
BEGIN
____________ times INT;
IF ( ____________ ='社长') THEN
BEGIN
SELECT COUNT(*) INTO times FROM tb_gs WHERE sno=NEW.sno AND ____________;
IF ( times > ________ ) THEN
BEGIN
SET NEW.role='社员';
SET @str='每个学生只能在一个社团担任社长!';
END;
END IF;
END;
END IF;
END //
DELIMITER ;
/*激活触发器*/
INSERT INTO tb_gs VALUES('g202','s201501103','2022-04-18','社长'); /*s201501103已经担任其他团的社长*/
INSERT INTO tb_gs VALUES('g102','s201501201','2017-04-18','社长'); /*s201501201没有参加过社团*/
INSERT INTO tb_gs VALUES('g102','s201605104','2017-04-18','社长'); /*s201605104作为社员参加过社团*/
触发器 tr_gs 逐空详细解析
第1个空:DECLARE
____________ times INT;
答案:DECLARE
解析:
- 声明局部变量的关键字
- 语法:
DECLARE 变量名 数据类型 - 这里声明
times变量,用于统计该学生担任社长的社团数量
第2个空:NEW.role
IF ( ____________ ='社长') THEN
答案:NEW.role
解析:
NEW是触发器中的特殊变量,代表新插入的行NEW.role是新插入记录的职务字段- 判断插入的职务是否为“社长”
第3个空:role='社长'
SELECT COUNT(*) INTO times FROM tb_gs WHERE sno=NEW.sno AND ____________;
答案:role = '社长'
解析:
- 统计该学生(
NEW.sno)已经担任社长的社团数量 - 条件:
role = '社长'筛选出职务为社长的记录 - 如果已经担任其他社团的社长,则
times > 0
第4个空:0
IF ( times > ________ ) THEN
答案:0
解析:
- 判断该学生是否已经担任其他社团的社长
- 如果
times > 0,说明已经担任社长 - 此时不允许再插入为社长,自动改为社员
完整代码
DELIMITER //
CREATE TRIGGER tr_gs BEFORE INSERT
ON tb_gs FOR EACH ROW
BEGIN
DECLARE times INT;
IF (NEW.role = '社长') THEN
BEGIN
SELECT COUNT(*) INTO times FROM tb_gs WHERE sno = NEW.sno AND role = '社长';
IF (times > 0) THEN
BEGIN
SET NEW.role = '社员';
SET @str = '每个学生只能在一个社团担任社长!';
END;
END IF;
END;
END IF;
END //
DELIMITER ;
触发器功能说明
功能:防止一个学生在多个社团担任社长
执行逻辑:
1. 用户插入新记录(加入社团)
2. 检查新记录的职务是否是“社长”
↓ 是社长
3. 统计该学生已经担任社长的社团数量
↓
4. 如果已经担任社长(times > 0)
↓
5. 自动将职务改为“社员”
↓
6. 设置提示信息 @str
触发示例解析
示例1(已担任社长)
INSERT INTO tb_gs VALUES('g202','s201501103','2022-04-18','社长');
s201501103已经是其他社团的社长- 触发器检测到
times > 0 - 自动将
role改为'社员' - 实际插入:职务变为“社员”
示例2(未参加过社团)
INSERT INTO tb_gs VALUES('g102','s201501201','2017-04-18','社长');
s201501201没有参加过任何社团times = 0,条件不满足- 保持职务为“社长”正常插入
示例3(作为社员参加过)
INSERT INTO tb_gs VALUES('g102','s201605104','2017-04-18','社长');
s201605104参加过社团但只是社员,不是社长times = 0,条件不满足- 保持职务为“社长”正常插入
答案汇总
| 空位 | 答案 | 含义 |
|---|---|---|
| 第1空 | DECLARE | 声明变量关键字 |
| 第2空 | NEW.role | 新插入记录的职务字段 |
| 第3空 | role = '社长' | 筛选社长职务 |
| 第4空 | 0 | 比较阈值 |
<html>
<meta http-equiv="Content-Type" content="text/html; charset=gbk" />
<?php
$host="localhost"; $user="root"; $pwd="";
//**********found**********
$db_name="____________";
$conn=mysql_connect($host,$user,$pwd )
or die("连接数据库服务器失败。".mysql_error());
//**********found**********
________________($db_name,$conn)
or die("连接数据库失败。".mysql_error());
mysql_query("set names 'gbk'");
?>
<body >
<br><br>
<div align="center"><font face="楷体" size="5" color="#006000">
<b>学院参加社团情况查询</b></font></div><br><br>
<form name="frm" method="post">
<table width="400" align="center">
<tr><td><span class="STYLE1">学院名称:</span></td>
<td><input type="text" name="DeptName" size="30"></td>
<td><input type="submit" name="select" value="查询"></td></tr>
</table>
</form>
<?php
//**********found**********
if(isset($_POST['____________']))
{
$DeptName=$_POST['DeptName'];
if(!$DeptName)
echo "<script> alert('输入不正确!')</script>;";
else
{
echo "<br>";
echo "<table width=500 border=2 align=center>";
echo "<tr><td>班级</td><td>姓名</td><td>性别</td><td>籍贯</td><td>社团名称</td><td>参加社团时间</td><td>承担的工作</td></tr>";
//**********found**********
$sql="select ___________, sname,sex,native,gname,joindate, role from tb_student s,tb_gs gs,tb_group g,tb_class c where s.classno=c.classno AND gs.sno=s.sno AND gs.gno=g.gno AND department ='$DeptName' order by CONVERT(c.classno USING gbk) desc,CONVERT(gname USING gbk)";
$result=mysql_query($sql);
//**********found**********
while($row=mysql_fetch_row(_____________)
{list($CLASS,$SNAME,$SEX,$NATIVE,$GNAME,$JOINDATE,$ROLE)=$row;
echo "<tr><td>$CLASS</td><td>$SNAME</td><td>$SEX</td><td>$NATIVE</td><td>$GNAME</td><td>$JOINDATE</td><td>$ROLE</td></tr>";
}
echo "</table>";
}
}
?>
</body>
</html>
PHP程序逐空详细解析
第1个空:db_club
$db_name="____________";
答案:db_club
解析:
- 根据题目背景,这是学生活动俱乐部数据库
- 数据库名称应为
db_club - 该数据库包含社团信息表、学生信息表、班级信息表等
第2个空:mysql_select_db
________________($db_name,$conn)
答案:mysql_select_db
解析:
- 选择数据库的函数
- 语法:
mysql_select_db(数据库名, 连接资源) - 第1个参数:数据库名称
$db_name - 第2个参数:数据库连接资源
$conn
第3个空:select
if(isset($_POST['____________']))
答案:select
解析:
- 判断表单是否已提交
- 表单提交按钮的
name属性是select - 当点击“查询”按钮时,
$_POST['select']被设置
表单中的对应代码:
<input type="submit" name="select" value="查询">
第4个空:c.classno
$sql="select ___________, sname,sex,native,gname,joindate, role from tb_student s,tb_gs gs,tb_group g,tb_class c where ...";
答案:c.classno
解析:
- 查询结果需要显示班级信息
- 后面代码中有
list($CLASS,$SNAME,...)对应输出 $CLASS对应第一个字段,即班级编号- 需要从班级表
tb_class中查询classno字段
完整字段对应:
| 输出位置 | 字段 | 别名/来源 |
|---|---|---|
| 第1列 | $CLASS | c.classno |
| 第2列 | $SNAME | s.sname |
| 第3列 | $SEX | s.sex |
| 第4列 | $NATIVE | s.native |
| 第5列 | $GNAME | g.gname |
| 第6列 | $JOINDATE | gs.joindate |
| 第7列 | $ROLE | gs.role |
第5个空:$result)
while($row=mysql_fetch_row(_____________)
答案:$result)
解析:
mysql_fetch_row()函数需要传入结果集资源- 前面
$result=mysql_query($sql)执行查询返回结果集 - 需要将
$result作为参数传入 - 注意括号闭合:
mysql_fetch_row($result)
正确写法:
while($row = mysql_fetch_row($result))
完整代码
<html>
<meta http-equiv="Content-Type" content="text/html; charset=gbk" />
<?php
$host="localhost"; $user="root"; $pwd="";
//**********found**********
$db_name="db_club";
$conn=mysql_connect($host,$user,$pwd )
or die("连接数据库服务器失败。".mysql_error());
//**********found**********
mysql_select_db($db_name,$conn)
or die("连接数据库失败。".mysql_error());
mysql_query("set names 'gbk'");
?>
<body >
<br><br>
<div align="center"><font face="楷体" size="5" color="#006000">
<b>学院参加社团情况查询</b></font></div><br><br>
<form name="frm" method="post">
<table width="400" align="center">
<tr><td><span class="STYLE1">学院名称:</span></td>
<td><input type="text" name="DeptName" size="30"></td>
<td><input type="submit" name="select" value="查询"></td>
</tr>
</table>
</form>
<?php
//**********found**********
if(isset($_POST['select']))
{
$DeptName=$_POST['DeptName'];
if(!$DeptName)
echo "<script> alert('输入不正确!')</script>;";
else
{
echo "<br>";
echo "<table width=500 border=2 align=center>";
echo "<tr><th>班级</th><th>姓名</th><th>性别</th><th>籍贯</th><th>社团名称</th><th>参加社团时间</th><th>承担的工作</th></tr>";
//**********found**********
$sql="select c.classno, sname,sex,native,gname,joindate, role from tb_student s,tb_gs gs,tb_group g,tb_class c where s.classno=c.classno AND gs.sno=s.sno AND gs.gno=g.gno AND department ='$DeptName' order by CONVERT(c.classno USING gbk) desc,CONVERT(gname USING gbk)";
$result=mysql_query($sql);
//**********found**********
while($row=mysql_fetch_row($result))
{list($CLASS,$SNAME,$SEX,$NATIVE,$GNAME,$JOINDATE,$ROLE)=$row;
echo "<tr><td>$CLASS</td><td>$SNAME</td><td>$SEX</td><td>$NATIVE</td><td>$GNAME</td><td>$JOINDATE</td><td>$ROLE</td></tr>";
}
echo "</table>";
}
}
?>
</body>
</html>
程序功能说明
功能:按学院名称查询该学院学生参加社团的情况
执行流程:
- 用户输入学院名称,点击“查询”
- 四表连接查询:
tb_student(学生表)tb_class(班级表)→ 关联学院tb_gs(学生社团表)tb_group(社团表)
- 输出:班级、姓名、性别、籍贯、社团名称、参加时间、职务
答案汇总
| 空位 | 答案 | 说明 |
|---|---|---|
| 第1空 | db_club | 数据库名称 |
| 第2空 | mysql_select_db | 选择数据库函数 |
| 第3空 | select | 表单提交按钮名称 |
| 第4空 | c.classno | 班级编号字段 |
| 第5空 | $result) | 结果集资源参数 |
发表回复