SQL:用AI软件来完成sql的触发器的使用

说明:本章主要使用baidu comate 的AI软件来完成

1.创建表

问题1:帮我创建2个表student与score表,要求student表有id,createDate,userName,phone,age,sex,introduce,

要求score表有id,scoreName,result,studentId(student表的id外键)。
要求student表中插入5条学生信息,都要是中文的。
要求score表中对应studentId插入10条信息,每个学生ID要有2个科目的成绩。
给出DDL与DML语句。

AI:下面是DDL(数据定义语言)用于创建studentscore表,以及DML(数据操作语言)用于插入数据的SQL语句。

DDL语句:

sql 复制代码
-- 创建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
);

DML语句:

首先,插入5条学生信息到student表中:

sql 复制代码
-- 插入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表中插入对应的成绩信息,每个学生两个科目:

sql 复制代码
-- 假设已经插入的学生信息中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语句。

2.插入数据

问题2:帮我根据两个DDL创建一个插入信息的存储过程,使用循环先插入10条学生表信息,再根据插入的学生表信息插入100条对应studentId的score成绩, 所有信息随机生成,学生表的自增序号从6开始。不允许使用DECLARE,使用set类声明变量。

AI:根据您的要求,以下是使用SET来声明变量,并使用循环插入学生信息和成绩的存储过程。请注意,MySQL的存储过程不支持直接使用SET来声明循环变量,但可以使用SET来更新变量的值。对于循环,我们将使用REPEAT ... UNTIL结构。

sql 复制代码
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();

在这个存储过程中,我们首先使用ALTER TABLE语句设置student表的自增起始值为6。

接着,使用REPEAT ... UNTIL循环结构来插入10条随机学生信息。在每次循环中,我们更新@counter变量来追踪循环的次数,并使用INSERT INTO语句插入一条随机的学生记录。使用LAST_INSERT_ID()函数获取最后插入的学生ID,并将其保存在@lastStudentId变量中。

然后,我们再次使用REPEAT ... UNTIL循环来插入100条随机成绩信息。在每次循环中,我们随机选择一个已存在的学生ID,并插入一条随机的成绩记录。

最后,通过调用CALL InsertStudentsAndScores();来执行这个存储过程。

请注意,这里的随机电话号码生成逻辑可能不符合实际的电话号码格式要求,您可能需要根据实际情况调整生成电话号码的逻辑。此外,由于随机性,有可能出现同一个学生被关联多条成绩记录的情况,这符合您的要求,但可能不符合某些实际场景。如果需要每个学生恰好有10条成绩记录,那么您需要设计更复杂的逻辑来确保这一点。

3.实现多表联合查询

问题3:帮我创建一个多表联合查询以student为主表,查看学生的所有科目成绩总分。

AI:要创建一个多表联合查询,以student表为主表,查看学生的所有科目成绩总分,你可以使用SQL的JOIN语句配合GROUP BYSUM函数来实现。以下是一个示例查询:

sql 复制代码
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;

这个查询做了以下几件事情:

  1. 使用JOIN语句将student表和score表连接起来,通过studentId字段进行匹配。

  2. 使用SELECT语句选择需要显示的字段,包括学生的ID、姓名和总分。这里使用别名(如student_idstudent_name)使结果更清晰。

  3. 使用SUM(sc.result)计算每个学生的所有科目成绩总分。

  4. 使用GROUP BY语句按学生的ID和姓名对结果进行分组,这样每个学生的总分只会出现一次。

请注意,这个查询假设每个学生可能有多个成绩记录(即score表中可能有多行与同一个studentId相关联)。如果score表中每个学生只有一个成绩记录,那么这个查询仍然有效,但SUM函数在这种情况下其实是多余的,因为它只是对单个值进行求和。

另外,这个查询没有处理没有成绩记录的学生的情况。如果你想要包括那些没有成绩记录的学生,并显示他们的总分为0,你需要使用LEFT JOIN而不是JOIN。这样,即使score表中没有与某个学生ID匹配的记录,该学生仍然会出现在结果集中,但总分将为0。

4.触发器的使用

问题4:帮我创建一个修改score表scoreName的触发器,当修改scoreName的时候触发,判断修改的scoreName是否是数学,如果是数学就改成(天书)。

并且给出测试示例。

AI:要创建一个触发器,当score表中的scoreName字段被修改时,检查新值是否为"数学",如果是,则将其改为"天书",你可以按照以下步骤进行:

首先,创建触发器:

sql 复制代码
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表中:

sql 复制代码
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为"数学"的记录,并查看是否触发器正常工作:

sql 复制代码
UPDATE score SET scoreName = '数学' WHERE id = 1; -- 假设id为1的记录原本scoreName就是'数学'

执行上述UPDATE语句后,由于触发器的作用,scoreName字段的值不会变成"数学",而是会变成"天书"。

为了验证结果,可以查询score表:

sql 复制代码
SELECT * FROM score;

你应该能看到id为1的记录的scoreName字段现在是"天书",而不是"数学"。

请注意,如果scoreName字段的值原本就不是"数学",则触发器不会有任何效果,scoreName字段的值将按照UPDATE语句中指定的新值进行更新。

还要确保在创建触发器之前,score表中没有名为trg_update_scoreName_to_tianshu的触发器存在,否则你会得到一个错误,因为MySQL不允许重名的触发器。如果之前已经创建了同名的触发器,你需要先删除它,可以使用以下命令:

sql 复制代码
DROP TRIGGER IF EXISTS trg_update_scoreName_to_tianshu;

然后再创建新的触发器。

5.游标的使用

问题5:创建一个两个表的综合【游标查询】,要求根据学生姓名进行查询,查询的结果返回两个表的综合信息。

AI:为了创建一个综合两个表的游标查询,并根据学生姓名来检索信息,我们可以使用存储过程结合游标来实现。在这个例子中,我们假设你希望查询学生的信息以及他们所有的成绩(不包含成绩表的id)。

首先,我们需要编写一个存储过程,该过程将接收学生姓名作为参数,并使用游标来遍历查询结果。以下是一个可能的实现:

sql 复制代码
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 ;

现在,我们有了这个存储过程GetStudentInfoAndScores,它接受一个学生姓名作为参数,并返回该学生的所有信息以及他们的成绩。请注意,由于一个学生可能有多个成绩,因此每个学生的信息将会被重复打印,每次打印都附带一个不同的成绩。

要调用这个存储过程并获取结果,你可以这样做:

sql 复制代码
CALL GetStudentInfoAndScores('目标学生姓名');

请替换'目标学生姓名'为你想要查询的学生的实际姓名。调用存储过程后,你将看到该学生的所有信息以及他们所有的成绩。

注意:这个实现假设每个学生至少有一个成绩记录。如果没有成绩记录,这个学生将不会出现在结果中。如果你希望即使学生没有成绩也显示他们的信息(例如,显示成绩为NULL或空字符串),你应该使用LEFT JOIN而不是JOIN

相关推荐
十叶知秋27 分钟前
【jmeter】jmeter的线程组功能的详细介绍
数据库·jmeter·性能测试
瓜牛_gn2 小时前
mysql特性
数据库·mysql
奶糖趣多多3 小时前
Redis知识点
数据库·redis·缓存
数新网络4 小时前
《深入浅出Apache Spark》系列②:Spark SQL原理精髓全解析
大数据·sql·spark
CoderIsArt4 小时前
Redis的三种模式:主从模式,哨兵与集群模式
数据库·redis·缓存
师太,答应老衲吧6 小时前
SQL实战训练之,力扣:2020. 无流量的帐户数(递归)
数据库·sql·leetcode
Channing Lewis7 小时前
salesforce case可以新建一个roll up 字段,统计出这个case下的email数量吗
数据库·salesforce
毕业设计制作和分享8 小时前
ssm《数据库系统原理》课程平台的设计与实现+vue
前端·数据库·vue.js·oracle·mybatis
ketil278 小时前
Redis - String 字符串
数据库·redis·缓存
NiNg_1_2348 小时前
高级 SQL 技巧详解
sql