首页 > 数据库 >SQL 实验

SQL 实验

时间:2023-11-07 17:33:05浏览次数:34  
标签:number t1 score 实验 student SQL where select

登入

mysql -uroot -hlocalhost -p123456

建库

create database mysql_test;
use mysql_test;

基础

建表

create table if not exists student_info(
	id int primary key auto_increment,
  number int not null unique,
  name varchar(100) not null
);

create table if not exists student_score(
	id int primary key auto_increment,
  number int not null,
  subject varchar(100) not null,
  score int
);

添加数据

insert into student_info(number,name) values
(1,'Alice'),(2,'Bob'),(3,'Tim');

insert into student_score (number, subject, score) values
(1,'Math',90),(1,'English',80),(1,'C Programming', 70),
(2,'Math',70),(2,'English',70),(2,'C Programing', NULL);

更新数据

select * from student_score;

update student_score set score = 80 where number = 2 and subject = 'Math';
update student_score set subject = 'C Programming' where number = 2 and score is null;

select * from student_score;

查询数据

单表查询
逻辑视角
select * from student_info where number = 2;
select * from student_info where number between 1 and 2;

select * from student_score where number = 1 and subject = 'Math';
select * from student_score where number = 1 or subject = 'Math';
集合视角
# 交集
select * from student_score where number = 1
intersect
select * from student_score where subject = 'Math';

# 并集
select * from student_score where number = 1
union
select * from student_score where subject = 'Math';
分组查询
select subject from student_score group by subject;
统计函数
select subject, count(score), max(score), min(score), avg(score) 
from student_score group by subject
order by avg(score) desc;
多表查询
子查询
# 无关子查询
select subject, score from student_score
where number = (select number from student_info where name = 'Alice');

# 相关子查询
select name, number from student_info where exists (select * from student_score where student_info.number = student_score.number);
连接查询
# 内连接
select * from student_info, student_score where name = 'Alice';
连接分类
  • 内外连接唯一差异:对 on 子句的处理逻辑不通

    • 内连接中,不符合 on 子句的记录会被抛弃,所以内连接中 where 语句等效于 on 语句

    • 外连接中,驱动表中不符合 on 子句的记录仍会被保留

      驱动表:第一次被查询的表

      驱动表的查询结果会作为后续被查询的表的条件
      → 驱动表的查询结果数量直接影响被驱动表被查询的次数

      • 左边为驱动表 → 左连接
      • 右边为驱动表 → 右连接
# (内)连接
select * from student_info inner join student_score;
# 左(外)连接:si 表中不符合 si.number = ss.number 的记录被保留
select * from student_info as si left join student_score as ss on si.number = ss.number;
# 右(外)连接:ss 表中不符合 si.number = ss.number 的记录被保留
select * from student_info as si right join student_score as ss on si.number = ss.number;
# 对比样例

# 前情提要:假设 t1 t2 中不存在两条记录,使得 t1.m1 = t2.m2; 表中数据如下所示
select * from t1;
+------+------+
| m1   | n1   |
+------+------+
|    1 | a    |
|    2 | b    |
|    3 | c    |
+------+------+
3 rows in set (0.00 sec)

select * from t2;
+------+------+
| m2   | n2   |
+------+------+
|    4 | c    |
|    5 | d    |
+------+------+
2 rows in set (0.00 sec)

# 内连接,但凡不符合 on 过滤条件的,都舍弃
select * from t1 inner join t2 on t1.m1 = t2.m2;
Empty set (0.00 sec)

# 外连接,驱动表中不符合 on 过滤条件的,仍然保留
# 左外连接 → 左边作为驱动表,保留左边
select * from t1 left join t2 on t1.m1 = t2.m2;
+------+------+------+------+
| m1   | n1   | m2   | n2   |
+------+------+------+------+
|    1 | a    | NULL | NULL |
|    2 | b    | NULL | NULL |
|    3 | c    | NULL | NULL |
+------+------+------+------+
3 rows in set (0.00 sec)

# 外连接,驱动表中不符合 on 过滤条件的,仍然保留
# 右外连接 → 右边作为驱动表,保留右边
select * from t1 right join t2 on t1.m1 = t2.m2;
+------+------+------+------+
| m1   | n1   | m2   | n2   |
+------+------+------+------+
| NULL | NULL |    4 | c    |
| NULL | NULL |    5 | d    |
+------+------+------+------+
数据删除
select * from student_info;
delete from student_info where name = 'Alice';
select * from student_info;
表删除
drop table if exists student_info;
drop table if exists student_score;

进阶

数据准备

CREATE TABLE students (
  id INT PRIMARY KEY,
  name VARCHAR(50),
  age INT,
  gender VARCHAR(10),
  grade VARCHAR(10),
  major VARCHAR(50),
  address VARCHAR(100)
);
INSERT INTO students (id, name, age, gender, grade, major, address) VALUES
(1, 'John Doe', 20, 'Male', 'Freshman', 'Computer Science', '123 Main St.'),
(2, 'Jane Smith', 19, 'Female', 'Sophomore', 'Engineering', '456 Elm St.'),
(3, 'Michael Johnson', 21, 'Male', 'Junior', 'Business Management', '789 Oak St.'),
(4, 'Emily Davis', 20, 'Female', 'Freshman', 'Psychology', '987 Maple Ave.'),
(5, 'Daniel Wilson', 22, 'Male', 'Senior', 'Political Science', '654 Pine St.'),
(6, 'Sophia Anderson', 19, 'Female', 'Sophomore', 'Biology', '321 Cedar St.'),
(7, 'David Martinez', 21, 'Male', 'Junior', 'Chemistry', '654 Birch Blvd.'),
(8, 'Olivia Thompson', 20, 'Female', 'Freshman', 'English Literature', '987 Oakwood Dr.'),
(9, 'William Rodriguez', 22, 'Male', 'Senior', 'Mathematics', '789 Elmwood Ave.'),
(10, 'Ava Taylor', 19, 'Female', 'Sophomore', 'Art History', '123 Pinecone Ln.');
CREATE TABLE student_grades (
  id INT NOT NULL AUTO_INCREMENT,
  name VARCHAR(50) NOT NULL,
  subject VARCHAR(50) NOT NULL,
  score INT NOT NULL,
  PRIMARY KEY (id)
);
INSERT INTO student_grades (id, name, subject, score) VALUES (1, 'John Doe', 'Math', 95), (2, 'Jane Smith', 'English', 88), (3, 'Michael Johnson', 'Science', 75), (4, 'Emily Davis', 'History', 92), (5, 'Daniel Wilson', 'Geography', 82), (6, 'Sophia Anderson', 'Biology', 90), (7, 'David Martinez', 'Chemistry', 78), (8, 'Olivia Thompson', 'Art', 85), (9, 'William Rodriguez', 'Physics', 87), (10, 'Ava Taylor', 'Music', 80);

create table t1 (m1 int, n1 char(1));
insert into t1 (m1, n1) values (1, 'a'), (2, 'b'), (3, 'c');
create table t2 (m2 int, n2 char(1));
insert into t2 (m2, n2) values (4, 'c'), (5, 'd');

视图

定位
  • 视图即别名:可以把视图看作是一个查询语句的别名,创建视图并不会保存结果集(类比 alias)

    create view 视图名称 as 查询语句
    
  • 视图即虚表:视图也可以称作虚拟表,我们可以像表一样对视图做增删改查操作

    # 查表能显示视图
    show tables;
    
示例
# 创建视图
create view male_students_view as select students.name, major, subject, score from students, student_grades where students.name = student_grades.name and gender = 'Male';

# 删除视图(像表一样)
drop view male_students_view;

存储程序

存储例程
存储函数
# 权限设置
set global log_bin_trust_function_creators = true;

# 将 MySQL 客户端分隔符从 ; 修改为 $,从而保证不会因为输入 ; 而导致客户端提前向服务端发送不完整的函数
delimiter $ 

# 创建函数
CREATE FUNCTION scaled_scores(name VARCHAR(50), subject VARCHAR(50))
RETURNS CHAR(1)
BEGIN
    DECLARE a INT;
    SET a = (
        SELECT score 
        FROM student_grades AS sg
        WHERE sg.name = name AND sg.subject = subject 
        ORDER BY score DESC 
        LIMIT 1
    );
    IF a >= 90 THEN RETURN 'A';
    ELSEIF a >= 80 THEN RETURN 'B';
    ELSEIF a >= 60 THEN RETURN 'C';
    ELSE RETURN 'D';
    END IF;
END;$

# 函数定义完成后复原分隔符
delimiter ; 

# 测试
select scaled_scores('John Doe', 'Math') ;
select scaled_scores('David Martinez', 'Chemistry');

# 删除
drop function scaled_scores;
存储过程
delimiter $
create procedure cursor_demo()
begin
	declare m_value int;
	declare n_value char(1);
	
	declare t1_record_cursor cursor for select m1, n1 from t1;
	
	open t1_record_cursor;
	
	fetch t1_record_cursor into m_value, n_value;
	select m_value,n_value;
	
	close t1_record_cursor;
end$
delimiter ;

call cursor_demo;
drop procedure cursor_demo;
delimiter $

create procedure cursor_demo()
begin
	declare m_value int;
	declare n_value char(1);
	declare done int default 0;
	
	declare t1_record_cursor cursor for select m1, n1 from t1;
	
	declare continue handler for not found set done = 1;
	
	open t1_record_cursor;
	
	flag: LOOP
		fetch t1_record_cursor into m_value, n_value;
		if done = 1 then
			leave flag;
		end if;
		select m_value, n_value;
	end LOOP flag;
	
	close t1_record_cursor;
end$

delimiter ;

call cursor_demo;
drop procedure cursor_demo;
触发器
delimiter $

create trigger bi_t1
before
insert
on t1
for each row
begin
	if new.m1 < 1 then
		set new.m1 = 1;
	elseif new.m1 > 10 then
	  set new.m1 = 10;
	end if;
end$

delimiter ;

select * from t1;
insert into t1 values(5, 'g'),(-1, 'h'),(100,'i');
select * from t1;

drop trigger bi_t1;
事件
delimiter $

create event insert_t1_event
on schedule
every 1 second
do
begin
  insert into t1 (m1, n1) values (6, 'k');
end$

delimiter ;
set GLOBAL event_scheduler = ON;
select * from t1;
# 间隔一段时间
select * from t1;
drop event insert_t1_event;

用户权限

用户
用户创建
select user, host from mysql.user;
create user 'user1'@'localhost' identified by '123456';
select user, host from mysql.user;
用户使用
mysql -uuser1 -hlocalhost -p123456
用户更新
alter user 'user1'@'localhost' identified by '1234567';
exit
mysql -uuser1 -hlocalhost -p123456
#mysql: [Warning] Using a password on the command line interface can be insecure.
#ERROR 1045 (28000): Access denied for user 'user1'@'localhost' (using password: YES)
mysql -uuser1 -hlocalhost -p1234567
exit
用户删除
drop user 'user1'@'localhost';
权限
权限查询
show grants for 'user1'@'localhost';
权限分配
grant select
on *.*
to 'user1'@'localhost'
with grant option;
权限收回
revoke select
on *.*
from 'user1'@'localhost';

删库

drop database mysql_test;

总结

模板整理

查询模板
SELECT [DISTINCT] 属性名
[FROM 表名]
[WHERE 表达式]
[GROUP BY 分组属性]
[HAVING 分组过滤条件]
[ORDER BY 排序属性]
[LIMIT 偏移量, 数量]

上述语句其实暗含了处理流程

  1. 通过 where 过滤记录
  2. 通过 group by 实现分组
  3. 通过 having 过滤分组结果
  4. 通过 order by 实现过滤后分组结果的排序
  5. 通过 limit 实现结果数量限制
存储函数模板
create function 函数名称(参数列表)
returns 返回值类型
begin
	函数体
	return 返回值
end
触发器模板
create trigger 触发器名称
{before | after}
{insert | delete | update}
on 表名
for each row
begin
	触发器内容
end
  • 作用时间
    • before:语句执行前执行触发器内容
    • after:语句执行后执行触发器内容
  • 作用范围:for each row
    • insert:影响范围是即将插入的新纪录
    • delete、update:影响范围是符合 where 子句过滤条件的记录
  • 记录版本:MySQL 服务器会对某条语句影响的所有记录依次调用我们自定义的触发器内容,所以针对每一条受影响的记录,我们需要一种方式来访问该记录中的内容
    • new:新纪录
      • insert 语义:准备插入的记录
      • delete 语义:无效
      • update 语义:修改后的记录
    • old:旧记录
      • insert 语义:无效
      • delete 语义:准备删除的记录
      • update 语义:修改前的记录

如果触发器只包含一条语句,可以省略 begin 和 end

事件模板
create event 事件名
on schedule
{ at 时间点 | every 期望的时间间隔[starts 开始日期和时间][end 结束日期和时间]}
do
begin
	具体的语句
end

参考书籍

《MySQL是怎样使用的:快速入门MySQL》小孩子4919

标签:number,t1,score,实验,student,SQL,where,select
From: https://www.cnblogs.com/ba11ooner/p/17815483.html

相关文章

  • 凝思80安装MySQL8.0.30
    概述本文记录在凝思80虚拟机上安装MySQL8.0.30。步骤下载MySQL8.0.30下载链接:https://downloads.mysql.com/archives/community/卸载已有MySQL查看当前已安装Mysqldpkg—get-selections|grepmysql卸载已安装的其他版本MySQLapt-get--purgeremovemysql-client-5.5apt-get--......
  • 20231107学习总结-大型数据库-实验1.熟悉常用的Linux操作和Hadoop操作
    实验1熟悉常用的Linux操作和Hadoop操作1.实验目的Hadoop运行在Linux系统上,因此,需要学习实践一些常用的Linux命令。本实验旨在熟悉常用的Linux操作和Hadoop操作,为顺利开展后续其他实验奠定基础。2.实验平台(1)操作系统:Linux(建议Ubuntu16.04或Ubuntu18.04);(2)Hadoop版本:3.1.3。3.......
  • 大型数据库实验一
    Linux操作和Hadoop操作实验报告一、熟悉的Linux操作1、切换到目录“/usr/local”2、切换到当前目录的上一级目录3、切换到当前登录系统的Linux系统的用户的自己的主文件夹4、查看/usr目录下的所有文件和目录5、在/tmp目录下,新建一个名为a的目录,并查看/tmp目录下已经有了......
  • 实验三
    #include<stdio.h>#include<stdlib.h>#include<time.h>#include<windows.h>#defineN80voidprint_text(intline,intcol,chartext[]);//函数声明voidprint_spaces(intn);//函数声明voidprint_blank_lines(intn);//函数声明intmain(){......
  • 云存储/视频监控管理平台EasyCVR,使用sqlite数据库出现卡顿该如何优化?
    视频集中存储/云存储/视频监控管理平台EasyCVR能在复杂的网络环境中,将分散的各类视频资源进行统一汇聚、整合、集中管理,实现视频资源的鉴权管理、按需调阅、全网分发、智能分析等。AI智能大数据视频分析EasyCVR平台已经广泛应用在工地、工厂、园区、楼宇、校园、仓储等场景中。有用......
  • MySQL学习(12)事务.md
    前言“古之欲正世调天下者,必先观国政,料事务,察民俗。“出自《管子·正世》,事务就是指要做的或所做的事情。一件事情要么做了,要么没做,才符合原则。转账不存在转了一半,也不存在我转给你10元,你却到账5元。ACID原则原子性(Atomicity)事务中的全部操作在数据库中是不可分割的,要么全部......
  • [转]PostgreSQL学习手册(目录)
       事实上之前有很长一段时间都在纠结是否有必要好好学习它,但是始终都没有一个很好的理由说服自己。甚至是直到这个项目最终决定选用PostgreSQL时,我都没有真正意识到学习它的价值,当时只是想反正和其它数据库差不多,能用就行了。然而有一天晚上,自己也不知道为什么,躺在床上开始......
  • 计网实验3
    1.建立网络拓扑执行dev3.sh脚本2.查看建立的NS列表3.查看各NS内的网络接口配置4.查看交换机桥接状态5.为虚拟网络拓扑中的各路由器配置静态路由6.关闭网卡offload功能,将运输层封装时需要的计算还给CPU7.打开两个终端模拟两个主机ns56A和ns57C8.在ns57C上启动抓包......
  • 实验5---Swing UI设计(简易计算器)
    一、实验目的本实验的目的是掌握JAVA容器类JFrame和JPanel的使用;掌握Swing常用布局的使用;掌握常用可视组件的使用。二、实验内容完成一个简单的计算器的功能。实现的效果图如下所示:  计算器实现的计算功能为:加、减、乘、除法、求余;“C”为清除,“<-“为退格等功能。三、......
  • php开发中常见的漏洞点(一) 基础sql注入
    前言本系列为小迪2022的学习笔记,仅用于自我记录。正文在一般情况下,一个网站的首页大致如下在上方存在着各种各样的导航标签、链接。而一般情况下网站的导航会用参数进行索引的编写,比如id、page等等比如上面的链接格式,当用户访问不同页面时id参数值也会跟着变化,比如我让id=2......