赞
踩
说明:本章主要使用baidu comate 的AI软件来完成
AI:下面是DDL(数据定义语言)用于创建student
和score
表,以及DML(数据操作语言)用于插入数据的SQL语句。
DDL语句:
-
- -- 创建student表
- CREATE TABLE student (
- id INT PRIMARY KEY AUTO_INCREMENT,
- createDate DATE NOT NULL,
- userName VARCHAR(50) NOT NULL,
- phone VARCHAR(20) NOT NULL,
- age INT NOT NULL,
- sex VARCHAR(10) NOT NULL,
- introduce TEXT
- );
-
-
- -- 创建score表,其中studentId是student表的外键
- CREATE TABLE score (
- id INT PRIMARY KEY AUTO_INCREMENT,
- scoreName VARCHAR(50) NOT NULL,
- result DECIMAL(5,2) NOT NULL,
- studentId INT,
- FOREIGN KEY (studentId) REFERENCES student(id) ON DELETE CASCADE ON UPDATE CASCADE
- );
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
DML语句:
首先,插入5条学生信息到student
表中:
-
- -- 插入5条学生信息
- INSERT INTO student (createDate, userName, phone, age, sex, introduce) VALUES
- ('2023-01-01', '张三', '13800138000', 20, '男', '来自北京,喜欢数学。'),
- ('2023-02-02', '李四', '13900139000', 21, '女', '来自上海,擅长英语。'),
- ('2023-03-03', '王五', '13700137000', 22, '男', '来自深圳,喜欢编程。'),
- ('2023-04-04', '赵六', '13600136000', 19, '女', '来自成都,爱好音乐。'),
- ('2023-05-05', '孙七', '13500135000', 20, '男', '来自武汉,擅长物理。');
然后,根据student
表中的id
,向score
表中插入对应的成绩信息,每个学生两个科目:
-
- -- 假设已经插入的学生信息中id分别为1, 2, 3, 4, 5
-
- -- 插入成绩信息,每个学生两条记录
- INSERT INTO score (scoreName, result, studentId) VALUES
- ('数学', 90.50, 1),
- ('英语', 85.25, 1),
- ('语文', 88.75, 2),
- ('物理', 92.00, 2),
- ('化学', 78.50, 3),
- ('生物', 82.25, 3),
- ('历史', 95.00, 4),
- ('地理', 89.75, 4),
- ('政治', 76.50, 5),
- ('体育', 87.00, 5);
注意:
上述DML语句中插入的id
值是根据假设的,实际操作中你需要根据student
表实际插入数据后自增生成的id
来填写对应的studentId
。
result
字段是成绩,这里使用了DECIMAL(5,2)
类型来存储,确保可以保存小数且保留两位小数。
createDate
字段使用的是DATE
类型,实际插入时需要按照YYYY-MM-DD
的格式提供日期值。
introduce
字段是文本类型,可以存储较长的介绍信息。
外键约束使用了ON DELETE CASCADE ON UPDATE CASCADE
,这表示当student
表中的id
被删除或更新时,score
表中对应的记录也会被级联删除或更新。这有助于保持数据的一致性。
请根据你的数据库环境和实际情况调整上述SQL语句。
AI:根据您的要求,以下是使用SET
来声明变量,并使用循环插入学生信息和成绩的存储过程。请注意,MySQL的存储过程不支持直接使用SET
来声明循环变量,但可以使用SET
来更新变量的值。对于循环,我们将使用REPEAT ... UNTIL
结构。
- DELIMITER //
-
- CREATE PROCEDURE InsertStudentsAndScores()
- BEGIN
- -- 设置student表的自增起始值为6
- ALTER TABLE student AUTO_INCREMENT = 6;
-
- -- 初始化变量
- SET @counter = 0;
- SET @lastStudentId = 0;
-
- -- 插入10条随机学生信息
- REPEAT
- SET @counter = @counter + 1;
-
- INSERT INTO student (createDate, userName, phone, age, sex, introduce)
- VALUES (
- CURDATE() - INTERVAL FLOOR(RAND() * 365) DAY, -- 随机日期
- CONCAT('Student', FLOOR(RAND() * 1000000)), -- 随机用户名
- CONCAT('1', LPAD(FLOOR(RAND() * 900000000), 9, '0')), -- 随机电话号码
- FLOOR(RAND() * 100) + 1, -- 随机年龄(1-100)
- CASE FLOOR(RAND() * 2) WHEN 0 THEN 'Male' ELSE 'Female' END, -- 随机性别
- CONCAT('This is a random introduction for student ', CONCAT('Student', FLOOR(RAND() * 1000000)), '.') -- 随机介绍
- );
-
- -- 获取最后插入的学生ID
- SELECT LAST_INSERT_ID() INTO @lastStudentId;
-
- UNTIL @counter >= 10 END REPEAT;
-
- -- 初始化变量,准备插入成绩
- SET @counter = 0;
-
- -- 插入100条随机成绩信息
- REPEAT
- SET @counter = @counter + 1;
-
- -- 随机选择一个已存在的学生ID
- SET @studentId = FLOOR(@lastStudentId * RAND()) + 6;
- IF @studentId > @lastStudentId THEN
- SET @studentId = @lastStudentId; -- 如果随机生成的ID超出了范围,则取最大值
- END IF;
-
- INSERT INTO score (scoreName, result, studentId)
- VALUES (
- CONCAT('Score', FLOOR(RAND() * 1000)), -- 随机成绩名称
- ROUND(RAND() * 100, 2), -- 随机成绩,范围0-100
- @studentId -- 随机选择的学生ID
- );
-
- UNTIL @counter >= 100 END REPEAT;
- END //
-
- DELIMITER ;
-
-
- -- 调用存储过程
- CALL InsertStudentsAndScores();
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
在这个存储过程中,我们首先使用ALTER TABLE
语句设置student
表的自增起始值为6。
接着,使用REPEAT ... UNTIL
循环结构来插入10条随机学生信息。在每次循环中,我们更新@counter
变量来追踪循环的次数,并使用INSERT INTO
语句插入一条随机的学生记录。使用LAST_INSERT_ID()
函数获取最后插入的学生ID,并将其保存在@lastStudentId
变量中。
然后,我们再次使用REPEAT ... UNTIL
循环来插入100条随机成绩信息。在每次循环中,我们随机选择一个已存在的学生ID,并插入一条随机的成绩记录。
最后,通过调用CALL InsertStudentsAndScores();
来执行这个存储过程。
请注意,这里的随机电话号码生成逻辑可能不符合实际的电话号码格式要求,您可能需要根据实际情况调整生成电话号码的逻辑。此外,由于随机性,有可能出现同一个学生被关联多条成绩记录的情况,这符合您的要求,但可能不符合某些实际场景。如果需要每个学生恰好有10条成绩记录,那么您需要设计更复杂的逻辑来确保这一点。
AI:要创建一个多表联合查询,以student
表为主表,查看学生的所有科目成绩总分,你可以使用SQL的JOIN
语句配合GROUP BY
和SUM
函数来实现。以下是一个示例查询:
- SELECT
- s.id AS student_id,
- s.userName AS student_name,
- SUM(sc.result) AS total_score
- FROM
- student s
- JOIN
- score sc ON s.id = sc.studentId
- GROUP BY
- s.id, s.userName;
这个查询做了以下几件事情:
使用JOIN
语句将student
表和score
表连接起来,通过studentId
字段进行匹配。
使用SELECT
语句选择需要显示的字段,包括学生的ID、姓名和总分。这里使用别名(如student_id
和student_name
)使结果更清晰。
使用SUM(sc.result)
计算每个学生的所有科目成绩总分。
使用GROUP BY
语句按学生的ID和姓名对结果进行分组,这样每个学生的总分只会出现一次。
请注意,这个查询假设每个学生可能有多个成绩记录(即score
表中可能有多行与同一个studentId
相关联)。如果score
表中每个学生只有一个成绩记录,那么这个查询仍然有效,但SUM
函数在这种情况下其实是多余的,因为它只是对单个值进行求和。
另外,这个查询没有处理没有成绩记录的学生的情况。如果你想要包括那些没有成绩记录的学生,并显示他们的总分为0,你需要使用LEFT JOIN
而不是JOIN
。这样,即使score
表中没有与某个学生ID匹配的记录,该学生仍然会出现在结果集中,但总分将为0。
AI:要创建一个触发器,当score
表中的scoreName
字段被修改时,检查新值是否为"数学",如果是,则将其改为"天书",你可以按照以下步骤进行:
首先,创建触发器:
- DELIMITER //
-
- CREATE TRIGGER trg_update_scoreName_to_tianshu
- BEFORE UPDATE ON score
- FOR EACH ROW
- BEGIN
- IF NEW.scoreName = '数学' THEN
- SET NEW.scoreName = '天书';
- END IF;
- END;
- //
-
- DELIMITER ;
这个触发器使用了BEFORE UPDATE
事件,意味着在score
表的行被更新之前,触发器会执行其内部的逻辑。如果NEW.scoreName
(代表将要被设置的新值)等于"数学",则将其更改为"天书"。
接下来,测试触发器:
首先,插入一些示例数据到score
表中:
- INSERT INTO score (scoreName, result, studentId) VALUES ('数学', 90.50, 1);
- INSERT INTO score (scoreName, result, studentId) VALUES ('英语', 85.25, 1);
- INSERT INTO score (scoreName, result, studentId) VALUES ('物理', 78.75, 2);
现在,尝试更新scoreName
为"数学"的记录,并查看是否触发器正常工作:
UPDATE score SET scoreName = '数学' WHERE id = 1; -- 假设id为1的记录原本scoreName就是'数学'
执行上述UPDATE
语句后,由于触发器的作用,scoreName
字段的值不会变成"数学",而是会变成"天书"。
为了验证结果,可以查询score
表:
SELECT * FROM score;
你应该能看到id为1的记录的scoreName
字段现在是"天书",而不是"数学"。
请注意,如果scoreName
字段的值原本就不是"数学",则触发器不会有任何效果,scoreName
字段的值将按照UPDATE
语句中指定的新值进行更新。
还要确保在创建触发器之前,score
表中没有名为trg_update_scoreName_to_tianshu
的触发器存在,否则你会得到一个错误,因为MySQL不允许重名的触发器。如果之前已经创建了同名的触发器,你需要先删除它,可以使用以下命令:
DROP TRIGGER IF EXISTS trg_update_scoreName_to_tianshu;
然后再创建新的触发器。
AI:为了创建一个综合两个表的游标查询,并根据学生姓名来检索信息,我们可以使用存储过程结合游标来实现。在这个例子中,我们假设你希望查询学生的信息以及他们所有的成绩(不包含成绩表的id)。
首先,我们需要编写一个存储过程,该过程将接收学生姓名作为参数,并使用游标来遍历查询结果。以下是一个可能的实现:
- DELIMITER //
-
- CREATE PROCEDURE GetStudentInfoAndScores(IN p_userName VARCHAR(50))
- BEGIN
- -- 声明变量来存储查询结果
- DECLARE done INT DEFAULT FALSE;
- DECLARE v_id INT;
- DECLARE v_createDate DATE;
- DECLARE v_userName VARCHAR(50);
- DECLARE v_phone VARCHAR(20);
- DECLARE v_age INT;
- DECLARE v_sex VARCHAR(10);
- DECLARE v_introduce TEXT;
- DECLARE v_scoreName VARCHAR(50);
- DECLARE v_result DECIMAL(5,2);
-
- -- 声明游标
- DECLARE cur CURSOR FOR
- SELECT
- s.id, s.createDate, s.userName, s.phone, s.age, s.sex, s.introduce,
- sc.scoreName, sc.result
- FROM student s
- JOIN score sc ON s.id = sc.studentId
- WHERE s.userName = p_userName;
-
- -- 声明NOT FOUND处理程序
- DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
-
- -- 打开游标
- OPEN cur;
-
- -- 读取游标中的数据
- read_loop: LOOP
- FETCH cur INTO v_id, v_createDate, v_userName, v_phone, v_age, v_sex, v_introduce, v_scoreName, v_result;
- IF done THEN
- LEAVE read_loop;
- END IF;
-
- -- 这里你可以对变量进行进一步的处理,比如打印或返回给调用者
- SELECT
- v_id AS student_id,
- v_createDate AS create_date,
- v_userName AS student_name,
- v_phone AS phone,
- v_age AS age,
- v_sex AS sex,
- v_introduce AS introduction,
- v_scoreName AS score_name,
- v_result AS result;
- END LOOP;
-
- -- 关闭游标
- CLOSE cur;
- END //
-
- DELIMITER ;
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
现在,我们有了这个存储过程GetStudentInfoAndScores
,它接受一个学生姓名作为参数,并返回该学生的所有信息以及他们的成绩。请注意,由于一个学生可能有多个成绩,因此每个学生的信息将会被重复打印,每次打印都附带一个不同的成绩。
要调用这个存储过程并获取结果,你可以这样做:
CALL GetStudentInfoAndScores('目标学生姓名');
请替换'目标学生姓名'
为你想要查询的学生的实际姓名。调用存储过程后,你将看到该学生的所有信息以及他们所有的成绩。
注意:这个实现假设每个学生至少有一个成绩记录。如果没有成绩记录,这个学生将不会出现在结果中。如果你希望即使学生没有成绩也显示他们的信息(例如,显示成绩为NULL或空字符串),你应该使用LEFT JOIN
而不是JOIN
。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。