Guass数据库实验(超详细熟悉基础操作、命令)

目录

实验一:建立数据库

实验二:数据库查询

插入数据

测试外键约束:尝试插入一个不存在的外键值

查询语句练习

查询“数据库系统”这门课的任课教师姓名

查询选修课程的学生学号、姓名、课程名称、成绩

查询高等数学成绩在 80 分以上的学生学号、姓名及成绩

查询张三选修课程的课程名称及对应成绩

查询所有学生的总成绩、平均成绩,并按总成绩降序排列

查询没有选修“数据库系统”的学生姓名

查询每门课程的最高成绩

查询至少选修了两门课程的学生姓名及课程数

实验三:数据库的物理设计

创建数据分区表

创建学生选课分区表

向分区中插入数据

查询主表中的数据,以及分区中的数据

体会外键约束

创建外键约束

测试外键约束

添加索引

权限管理

实验四:数据库开发

视图

创建视图

查询视图

 储存过程

创建存储过程:计算并保存学生的总成绩和总学分

调用储存过程

触发器

创建触发器

讨论视图,储存过程,触发器的使用范围以及优缺点

视图

储存过程

触发器


实验一:建立数据库

  • 购买云服务器后,启动,并使用cloudshell远程登陆

  • 使用DataStudio远程连接
  • 创建学籍与成绩管理系统

包含以下信息: 课程名称、课程代号、课程类型(必修、选修、任选)、学分、任课教师姓名、教师编号、教师职称、教师所属学院名称、教师所属学院代号、教师所授课程学生姓名、学生学号、学生所属学院名称、学生所属学院代号、学生所选课程、学生成绩。

-- 建立数据表

CREATE TABLE xyb (
    ydh CHAR(2) PRIMARY KEY,
    ymc VARCHAR(30) NOT NULL

);

CREATE TABLE xs (
    xh CHAR(10) PRIMARY KEY,
    xm VARCHAR(8) NOT NULL,
    ydh CHAR(2),
    bj VARCHAR(8),
    chrq DATE,
    xb VARCHAR(10),
    FOREIGN KEY (ydh) REFERENCES xyb(ydh)
);



CREATE TABLE js (
    jsbh CHAR(10) PRIMARY KEY,
    xm VARCHAR(8) NOT NULL,
    zc VARCHAR(6),
    ydh CHAR(2),
    FOREIGN KEY (ydh) REFERENCES xyb(ydh)
);

ALTER TABLE js
ALTER COLUMN xm TYPE VARCHAR(16);

ALTER TABLE js
ALTER COLUMN zc TYPE VARCHAR(16);

CREATE TABLE kc (
    kcbh CHAR(3) PRIMARY KEY,
    kc VARCHAR(20) NOT NULL,
    lx VARCHAR(10),
    xf NUMERIC(5,1)
);

CREATE TABLE sk (
    kcbh CHAR(3),
    jsbh CHAR(10),
    PRIMARY KEY (kcbh, jsbh),
    FOREIGN KEY (kcbh) REFERENCES kc(kcbh),
    FOREIGN KEY (jsbh) REFERENCES js(jsbh)
);

CREATE TABLE xk (
    xh CHAR(10),
    kcbh CHAR(3),
    jsbh CHAR(10),
    cj NUMERIC(5,1),
    PRIMARY KEY (xh, kcbh, jsbh),
    FOREIGN KEY (xh) REFERENCES xs(xh),
    FOREIGN KEY (kcbh, jsbh) REFERENCES sk(kcbh, jsbh)
);

CREATE INDEX idx_xs_ydh ON xs(ydh);

CREATE INDEX idx_js_ydh ON js(ydh);

CREATE INDEX idx_xk_cj ON xk(cj);

实验二:数据库查询

  • 插入数据

-- 插入数据
INSERT INTO xyb (ydh, ymc) VALUES
('01', '计算机学院'),
('02', '数学学院');

INSERT INTO xs (xh, xm, ydh, bj, chrq, xb) VALUES
('2023000001', '张三', '01', '计科一班', DATE '2004-09-01', '男'),
('2023000002', '李四', '01', '计科一班', DATE '2004-06-13', '女'),
('2023000003', '王五', '02', '数学一班', DATE '2003-11-23', '男'),
('2023000004', '赵六', '02', '数学二班', DATE '2004-03-03', '女'),
('2023000005', '孙七', '01', '计科二班', DATE '2005-01-17', '男');

-- 插入教师
INSERT INTO js (jsbh, xm, zc, ydh) VALUES
('T001', '王老师', '副教授', '01'),
('T002', '赵老师', '讲师', '02');

-- 插入课程
INSERT INTO kc (kcbh, kc, lx, xf) VALUES
('C01', '数据库系统', '必修', 3.0),
('C02', '高等数学', '必修', 4.0),
('C03', '操作系统', '选修', 2.0);

-- 授课关系
INSERT INTO sk (kcbh, jsbh) VALUES
('C01', 'T001'),
('C02', 'T002'),
('C03', 'T001');

-- 学生 2023000001 选课记录
INSERT INTO xk (xh, kcbh, jsbh, cj) VALUES
('2023000001', 'C01', 'T001', 85),  -- 张三选了“数据库系统”
('2023000001', 'C02', 'T002', 90),  -- 张三选了“高等数学”
('2023000001', 'C03', 'T001', 76);  -- 张三选了“操作系统”

-- 学生 2023000002 选课记录
INSERT INTO xk (xh, kcbh, jsbh, cj) VALUES
('2023000002', 'C01', 'T001', 80),  -- 李四选了“数据库系统”
('2023000002', 'C02', 'T002', 70),  -- 李四选了“高等数学”
('2023000002', 'C03', 'T001', 85);  -- 李四选了“操作系统”

-- 学生 2023000003 选课记录
INSERT INTO xk (xh, kcbh, jsbh, cj) VALUES
('2023000003', 'C01', 'T001', 88),  -- 王五选了“数据库系统”
('2023000003', 'C02', 'T002', 75),  -- 王五选了“高等数学”
('2023000003', 'C03', 'T001', 92);  -- 王五选了“操作系统”

-- 学生 2023000004 选课记录
INSERT INTO xk (xh, kcbh, jsbh, cj) VALUES
('2023000004', 'C01', 'T001', 90),  -- 赵六选了“数据库系统”
('2023000004', 'C02', 'T002', 60),  -- 赵六选了“高等数学”
('2023000004', 'C03', 'T001', 78);  -- 赵六选了“操作系统”

-- 学生 2023000005 选课记录
INSERT INTO xk (xh, kcbh, jsbh, cj) VALUES
('2023000005', 'C01', 'T001', 83),  -- 孙七选了“数据库系统”
('2023000005', 'C02', 'T002', 91),  -- 孙七选了“高等数学”
('2023000005', 'C03', 'T001', 87);  -- 孙七选了“操作系统”
  • 测试外键约束:尝试插入一个不存在的外键值

-- 假设学生学号 9999999999 并不存在
-- 假设课程 C99 或教师 T99 也不存在
-- 插入一条错误记录以测试外键约束

INSERT INTO xk (xh, kcbh, jsbh, cj) VALUES
('9999999999', 'C99', 'T99', 100);

实验结果:

  • 查询语句练习

查询“数据库系统”这门课的任课教师姓名

SELECT js.xm
FROM js
JOIN sk ON js.jsbh = sk.jsbh
JOIN kc ON kc.kcbh = sk.kcbh
WHERE kc.kc = '数据库系统';

查询结果

    查询选修课程的学生学号、姓名、课程名称、成绩

    SELECT xs.xh, xs.xm, kc.kc, xk.cj
    FROM xk
    JOIN xs ON xk.xh = xs.xh
    JOIN kc ON xk.kcbh = kc.kcbh;

    查询结果

      查询高等数学成绩在 80 分以上的学生学号、姓名及成绩

      SELECT xs.xh, xs.xm, xk.cj
      FROM xk
      JOIN xs ON xk.xh = xs.xh
      JOIN kc ON xk.kcbh = kc.kcbh
      WHERE kc.kc = '高等数学' AND xk.cj >= 80;

      查询结果

        查询张三选修课程的课程名称及对应成绩

        SELECT kc.kc, xk.cj
        FROM xk
        JOIN xs ON xk.xh = xs.xh
        JOIN kc ON xk.kcbh = kc.kcbh
        WHERE xs.xm = '张三';

        查询结果

          查询所有学生的总成绩、平均成绩,并按总成绩降序排列

          SELECT xs.xh, xs.xm, SUM(xk.cj) AS 总成绩, AVG(xk.cj) AS 平均成绩
          FROM xk
          JOIN xs ON xk.xh = xs.xh
          GROUP BY xs.xh, xs.xm
          ORDER BY 总成绩 DESC;

          查询结果

            查询没有选修“数据库系统”的学生姓名

            SELECT xm
            FROM xs
            WHERE xh NOT IN (
                SELECT xk.xh
                FROM xk
                JOIN kc ON xk.kcbh = kc.kcbh
                WHERE kc.kc = '数据库系统'
            );

            查询结果

            无结果

            查询每门课程的最高成绩

            SELECT kc.kc, MAX(xk.cj) AS 最高分
            FROM xk
            JOIN kc ON xk.kcbh = kc.kcbh
            GROUP BY kc.kc;

            查询结果

              查询至少选修了两门课程的学生姓名及课程数

              SELECT xs.xm, COUNT(*) AS 课程数
              FROM xk
              JOIN xs ON xk.xh = xs.xh
              GROUP BY xs.xh, xs.xm
              HAVING COUNT(*) >= 2;

              查询结果

              实验三:数据库的物理设计

              创建数据分区表

              • 创建学生选课分区表

              -- 创建主表(学生选课表),按照学号(xh)进行分区
              CREATE TABLE xk_partitioned (
                  xh CHAR(10),
                  kcbh CHAR(3),
                  jsbh CHAR(10),
                  cj NUMERIC(5,1),
                  PRIMARY KEY (xh, kcbh, jsbh)
              ) PARTITION BY RANGE (xh)
              (
                  PARTITION part_1 VALUES LESS THAN ('2023000011'),  -- 学号范围 2023000001 到 2023000010
                  PARTITION part_2 VALUES LESS THAN ('2023000021'),  -- 学号范围 2023000011 到 2023000020
                  PARTITION part_3 VALUES LESS THAN ('2023000031'),  -- 学号范围 2023000021 到 2023000030
                  PARTITION part_4 VALUES LESS THAN (MAXVALUE)      -- 其他学号
              );
                • 向分区中插入数据

                -- 向分区表中插入数据
                INSERT INTO xk_partitioned (xh, kcbh, jsbh, cj) VALUES
                ('2023000001', 'C01', 'T001', 85),  -- 属于分区1
                ('2023000002', 'C02', 'T002', 90),  -- 属于分区1
                ('2023000003', 'C03', 'T001', 76),  -- 属于分区1
                ('2023000004', 'C01', 'T001', 88),  -- 属于分区1
                ('2023000022', 'C02', 'T002', 72),  -- 属于分区2
                ('2023000023', 'C01', 'T001', 80),  -- 属于分区2
                ('2023000024', 'C02', 'T002', 70),  -- 属于分区2
                ('2023000032', 'C03', 'T001', 85),  -- 属于分区3
                ('2023000033', 'C01', 'T001', 75),  -- 属于分区3
                ('2023000034', 'C02', 'T002', 92);  -- 属于分区3
                  • 查询主表中的数据,以及分区中的数据

                  SELECT * FROM xk_partitioned;

                  -- 查询 part_1 分区的数据,学号范围 2023000001 到 2023000010
                  SELECT * FROM xk_partitioned PARTITION (part_1);

                  -- 查询 part_2 分区的数据,学号范围 2023000011 到 2023000020
                  SELECT * FROM xk_partitioned PARTITION (part_2);

                  -- 查询 part_3 分区的数据,学号范围 2023000021 到 2023000030
                  SELECT * FROM xk_partitioned PARTITION (part_3);

                  -- 查询 part_4 分区的数据,学号范围 2023000031 以后
                  SELECT * FROM xk_partitioned PARTITION (part_4);

                  无结果

                  体会外键约束

                  • 创建外键约束

                  -- 为 xk 表添加外键约束(学号引用 xs 表,课程编号和教师编号引用 sk 表)
                  ALTER TABLE xk
                  ADD CONSTRAINT fk_xh FOREIGN KEY (xh) REFERENCES xs(xh);
                  
                  ALTER TABLE xk
                  ADD CONSTRAINT fk_kcbh_jsbh FOREIGN KEY (kcbh, jsbh) REFERENCES sk(kcbh, jsbh);
                    • 测试外键约束

                    -- 向 xk 表插入无效数据(学号 '9999999999' 不存在于 xs 表中)
                    INSERT INTO xk (xh, kcbh, jsbh, cj) VALUES ('9999999999', 'C01', 'T001', 85);
                    
                    -- 插入数据(正确的学号和课程编号)
                    INSERT INTO xk (xh, kcbh, jsbh, cj) VALUES ('2023000001', 'C01', 'T001', 88);

                    执行结果

                    • 添加索引

                    -- 在学号(xh)和课程编号(kcbh)上创建索引
                    CREATE INDEX idx_xh_kcbh ON xk_partitioned (xh, kcbh);
                    
                    -- 在教师编号(jsbh)上创建索引
                    CREATE INDEX idx_jsbh ON xk_partitioned (jsbh);

                    当数据量很大时,就会体现出索引的高效率

                    • 权限管理

                    要注意的是,需要超级用户才能创建新的用户,所以需要切换到超级用户!!!

                    实验四:数据库开发

                    视图

                    • 创建视图

                    -- 创建一个视图,显示每个学生的总学分和成绩
                    CREATE VIEW student_summary AS
                    SELECT xs.xh, xs.xm, SUM(kc.xf) AS total_credits, AVG(xk.cj) AS average_score
                    FROM xk
                    JOIN xs ON xk.xh = xs.xh
                    JOIN kc ON xk.kcbh = kc.kcbh
                    GROUP BY xs.xh, xs.xm;
                    • 查询视图

                    -- 查询视图中的学生总学分和成绩
                    SELECT * FROM student_summary;

                    查询结果

                     储存过程

                    • 创建存储过程:计算并保存学生的总成绩和总学分

                    CREATE OR REPLACE PROCEDURE chen.calculate_student_summary()
                    AS  DECLARE BEGIN
                        -- 将学生的总成绩和学分保存到另一个表中
                        INSERT INTO student_summary (xh, xm, total_credits, average_score)
                        SELECT xs.xh, xs.xm, 
                               SUM(kc.xf) AS total_credits,  -- 计算总学分
                               AVG(xk.cj) AS average_score   -- 计算平均成绩
                        FROM xk
                        JOIN xs ON xk.xh = xs.xh         -- 连接学生表
                        JOIN kc ON xk.kcbh = kc.kcbh     -- 连接课程表
                        GROUP BY xs.xh, xs.xm;           -- 按学号和姓名分组
                    END;

                    调用储存过程

                    -- 调用存储过程,计算并保存学生的总成绩和平均分
                    CALL calculate_student_summary();

                    执行结果

                    注意:因为前面创建试图时,使用的名称就是student_summary,而在此创建的储存过程中也同样使用到了这个名称,但是我们知道视图并不是一张实际存在的表,只是记录了数据间的逻辑关系。所以insert操作是无法进行的,而解决方案就是,先将开始的视图删除,然后新创建一张表,进行储存过程操作。

                    触发器

                    • 创建触发器

                    -- 创建触发器函数:记录成绩更新操作
                    CREATE OR REPLACE FUNCTION record_grade_update()
                    RETURNS TRIGGER AS $$
                    BEGIN
                        -- 在成绩更新时记录操作
                        INSERT INTO grade_update_log (xh, old_grade, new_grade, update_time, update_user)
                        VALUES (NEW.xh, OLD.cj, NEW.cj, CURRENT_TIMESTAMP, current_user);
                        RETURN NEW;
                    END;
                    $$ LANGUAGE plpgsql;
                    
                    -- 创建触发器:当学生成绩更新时触发
                    CREATE TRIGGER grade_update_trigger
                    AFTER UPDATE ON xk
                    FOR EACH ROW
                    EXECUTE FUNCTION record_grade_update();

                    讨论视图,储存过程,触发器的使用范围以及优缺点

                    • 视图

                    1. 视图主要用于简化复杂的查询。通过将复杂的 SQL 查询封装在视图中,用户可以像查询普通表一样查询视图,从而提高查询的易用性和可维护性。
                    2. 视图可以作为数据访问的接口,限制用户对基础数据表的访问,只允许用户查询视图中的数据,从而提高数据的安全性。
                    3. 优点:简化复杂查询、安全性、易于维护
                    4. 缺点:性能开销比较大、视图不能直接更新
                    • 储存过程

                    1. 存储过程用于封装一组 SQL 语句,处理复杂的数据操作逻辑。
                    2. 可以通过存储过程确保一系列数据库操作要么全部成功,要么全部失败(通过事务处理)。
                    3. 优点:储存过程是预编译(性能好)、可用于管理事务(保证操作、数据的一致性)
                    4. 缺点:可维护性低、不同的数据库的储存过程可能不同(可迁移性弱)
                    • 触发器

                    1. 实现自动化操作
                    2. 触发器常用于自动记录数据的更改历史或日志
                    3. 优点:能够自动执行、具有数据验证机制
                    4. 缺点:性能开销大、触发器复杂时导致数据库操作的行为难以预测
                    评论
                    添加红包

                    请填写红包祝福语或标题

                    红包个数最小为10个

                    红包金额最低5元

                    当前余额3.43前往充值 >
                    需支付:10.00
                    成就一亿技术人!
                    领取后你会自动成为博主和红包主的粉丝 规则
                    hope_wisdom
                    发出的红包
                    实付
                    使用余额支付
                    点击重新获取
                    扫码支付
                    钱包余额 0

                    抵扣说明:

                    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
                    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

                    余额充值