SQL 九个功能:
数据查询 select
数据定义 create drop alter
数据操纵 insert update delete
数据控制 grant revoke
语法格式:
SELECT <目标表达式>
FROM
[WHERE <条件表达式>]
[GROUP BY <列名1> HAVING <条件表达式>] 注意:WHERE和HAVING不能同时出现
[ORDER BY <列名2> [ASC|DESC 降序 ]]
1.简单查询
SELECT * FROM STUDENT;
SELECT SNO,SNAME,SSEX,SAGE,SDEPT;
2 . 算术表达式
SELECT SNAME , 2020-SAGE
FROM STUDENT;
3.别名
SELECT SNAME name , 2020-SAGE
FROM STUDENT;
4.条件查询
SELECT SNAME,SAGE
FROM STUDENT
WHERE SAGE<20;
5.确定范围
SELECT SANME
FROM STUDENT
WHERE SAGE BETWEEN 20 AND 23;
6.IN子查询
SELECT SNAME,SSEX
FROM STUDENT
WHERE SDEPT IN(‘CS’,’IS’);
7.模糊查询
通配符 | 描述 | 例子 |
---|---|---|
% | 任意长度的字符串 | a%b,表示ab、acb、acdb |
_ | 任意单个字符 | a_b,表示acb、adb |
SELECT SNAME,SNO,SSEX
FROM STUDENT
WHERE SNAME LIKE ‘_阳%’;
8.空值查询
SELECT SNO,CNO
FROM SC
WHERE GRADE IS NULL;
9.与或查询
SELECT SNAME
FROM STUDENT
WHERE SDEPT=’CS’ AND SAGE<20;
SELECT SNAME,SSEX
FROM STUDENT
WHERE SDEPT=’CS’ OR SDEPT=’MA’ OR SDEPT=’IS’;
注意:AND运算符优先级高于OR运算符
10.排序查询
SELECT SNO,GRADE
FROM SC
WHERE CNO=’3’
ORDER BY GRADE DESC;
11.聚合查询
COUNT、SUM、AVG、MAX、MIN
注意:聚集函数只能用于SELECT子句和GROUP BY中的HAVING子句
例:
查询学生总人数。
SELECT COUNT(*) FROM Student ;
查询选修了课程的学生人数。
SELECT COUNT(DISTINCT Sno) FROM SC ;
计算1号课程的学生平均成绩。
SELECT AVG(Grade) FROM SC WHERE Cno = '1' ;
查询选修1号课程的学生最高分数。
SELECT MAX(Grade) FROM SC WHERE Cno = '1' ;
查询学生201215012选修课程的总学分数。
SELECT SUM(Ccredit) FROM SC, Course WHERE Sno = '201215012' AND SC.Cno = Course.Cno ;
12.分组查询
SELECT CNO,COUNT(SNO)
FROM SC
GROUP BY CNO;
SELECT SNO
FROM SC
GROUP BY SNO
HAVING COUNT(*)>3;
例:查询平均成绩大于等于90分的学生的学号和平均成绩
SELECT SNO,AVG(GRADE)
FROM SC
GROUP BY SNO
HAVING AVG(GRADE)>=90;
13.连接查询
SELECT STUDENT.*,SC.*
FROM STUDENT,SC
WHERE STUDENT.SNO=SC.SNO;
SELECT FIRST.CNO,SECOND.CPNO
FROM COURSE FIRST,COURSE SECOND
WHERE FIRST.CPNO=SECOND.CNO;
例:查询每个学生及其选修课程的情况。
SELECT Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade
FROM Student
LEFT JOIN SC
ON (Student.Sno = SC.Sno) ;
SELECT Student.Sno, Sname,Cname,Grade
FROM Student,SC,Course
WHERE Student.Sno = SC.Sno AND SC.Cno = Course.Cno ;
14.嵌套查询
SELECT SNAME
FROM STUDENT
WHERE SNO IN
(SELECT SNO
FROM SC
WHERE CNO='2');
例如:查询与”刘晨”在同一个系学习的学生
SELECT SDEPT
FROM STUDENT
WHERE SNAME='刘晨';
SELECT SNO,SNAME,SDEPT
FROM STUDENT
WHERE SDEPT='CS';
SELECT SNO,SNAME,SDEPT
FROM STUDENT
WHERE SDEPT IN
(SELECT SDEPT
FROM STUDENT
WHERE SNAME='刘晨');
15.带有ANY或ALL谓词的子查询
使用ANY或ALL谓词时必须同时使用比较运算,
> ANY:大于子查询结果中的某个值
> ALL:大于子查询结果中的所有值
< ANY:小于子查询结果中的某个值
< ALL:小于子查询结果中的所有值
>= ANY:大于等于子查询结果中的某个值
>= ALL:大于等于子查询结果中的所有值
<= ANY:小于等于子查询结果中的某个值
<= ALL:小于等于子查询结果中的所有值
= ANY:等于子查询结果中的某个值
= ALL:等于子查询结果中的所有值
!= ANY:不等于子查询结果中的某个值
!= ALL:不等于子查询结果中的任何一个值
例:查询非计算机科学系中比计算机科学系任意一个学生年龄小的学生姓名和年龄。
SELECT SNAME,SAGE
FROM STUDENT
WHERE SAGE <ANY(SELECT SAGE
FROM STUDENT
WHERE SDEPT='CS')
AND SDEPT <> 'CS';
1.插入单条数据
例如:将一个新学生元组(学号:201215128;姓名:陈冬;性别:男;所在系:IS;年龄:18岁)插入到Student表中。
INSERT INTO Student (Sno, Sname, Ssex, Sdept, Sage)
VALUES('201215128','陈冬','男','IS',18) ;
2.插入多条数据
例如:插入两条学生元组,插入信息自选。
INSERT INTO Student (Sno, Sname, Ssex, Sdept, Sage)
VALUES('888888','zs','男','MA',21), ('999999','ls','女','CS',20) ;
例:将学生888888的年龄改为18岁。
UPDATE Student
SET Sage = 18
WHERE Sno = '888888' ;
删除一条数据
例:删除学号为888888的学生记录。
DELETE FROM Student
WHERE Sno = '888888' ;
1.创建用户
CREATE USER 'user_name'@'host' IDENTIFIED BY 'password';
--user_name:要创建用户的名字。
--host:表示要这个新创建的用户允许从哪台机登陆,如果只允许从本机登陆,则 填 ‘localhost’ ,如果允许从远程登陆,则填 ‘%’
--password:新创建用户的登陆数据库密码,如果没密码可以不写。
2.权限授权
例1:把查询Student表权限授给用户U1。
GRANT SELECT
ON TABLE Student
TO U1 ;
例2:把对表SC的查询权限授予所有用户。
GRANT SELECT
ON TABLE SC
TO PUBLIC ;
例3:把查询Student表和修改学生学号的权限授给用户U4。
GRANT UPDATE(Sno), SELECT
ON TABLE Student
TO U4 ;
例4:把对表SC的INSERT权限授予U5用户,并允许他再将此权限授予其他用户。
GRANT INSERT
ON TABLE SC
TO U5
WITH GRANT OPTION ;
权限收回
例1:把用户U4修改学生学号的权限收回。
REVOKE UPDATE(Sno)
ON TABLE Student
FROM U4 ;
例2:收回所有用户对表SC的查询权限。
REVOKE SELECT
ON TABLE SC
FROM PUBLIC ;
例3:把用户U5对SC表的INSERT权限收回。
REVOKE INSERT
ON TABLE SC
FROM U5 CASCADE ;
例:通过角色来实现将一组权限授予一个用户。
1. 首先创建一个角色 R1
CREATE ROLE R1;
2. 然后使用GRANT语句,使角色R1拥有Student表的SELECT、UPDATE、INSERT权限
GRANT SELECT,UPDATE,INSERT
ON Student TO R1;
3. 将这个角色授予R2、R3、R4。使他们具有角色R1所包含的全部权限
grangt R1 to R2,R3,R4
4. 可以一次性通过R1来回收王平的这3个权限
REVOKE R1 FROM R1;
1.主键约束primary key
列级 sno char(20) PRIMARY KEY
表级 PRIMARY KEY(sno)
2.唯一性约束 unique
Sname char(20) UNIQUE
3.非空约束 not null
Came char(20) NOT NULL
4.外键约束 foreign key … references
FOREIGN KEY(Sno) REFERENCES Student(Sno)
5.检查约束check
CHECK(SSEX IN(‘男’,’女’));
例:建立学生选课表SC
Create table SC(
sno char(9),
Cno char(4),
Grade int(3) CHECK(grade>=0 and grade <=100),
PRIMARY KEY(sno),
FOREIGN KEY(sno) REFERENCES student(sno),
FOREIGN KEY(cno) REFERENCES course(cno)
);
1.拒绝执行
#拒绝删除
ON DELETE NO ACTION
2.级联操作
#级联更新
ON UPDATE CASCADE
#级联删除
ON DELETE CASCADE
3.设置为空
#删除置空
ON DELETE SET NULL
数据库设计过程
设计E-R图的两条准则
(1)属性不能再具有需要描述的性质。即属性必须是不可分的数据项,不能再由另一些属性组成
(2)属性不能与其他实体具有联系。联系只发生在实体之间
E-R图向关系模型的转换
E-R图向关系模型的转换要解决的问题
1)如何将实体型和实体间的联系转换为关系模式
2)如何确定这些关系模式的属性和码
转换内容
1)将E-R图转换为关系模型:
2)将实体、实体的属性和实体之间的联系转换为关系模式
例题1:
参考文章:实验七 数据库设计
1.概念结构设计
进行数据库概念模型的设计
实体:
系、教师、学生和课程。
各个实体的属性:
1.系:系编号、系名、地址
2.课程:课程号、课程名称、开课学期
3.学生:学号、学生姓名、性别、住址
4.教师:教工号、教师姓名、办公室
实体间的联系有:
1.每个系有一位系主任,有多位教师;
2.一个教师只能在一个系任职;
3.每个系开设多门不同课程;
4.一门课程只能由一个系负责开设;
5.每门课程只能由一个教师授课,一个教师可以讲授多门课程;
6.一个学生可以选修多门课程;一门课程也可以由多个学生选修。
2.逻辑结构设计
将概念模型转换成关系型逻辑模型,划实线为各个关系模式的主码,其余为外码。
系:(系编号
,系名,地址,系主任)
课程:(课程号
,课程名称,开课学期,系编号,教工号)
学生:(学号
,学生姓名,性别,住址,系编号)
教师:(教工号
,教师姓名,办公室,系编号)
选修:(课程号,学号
)
例题2:
某医院病房管理系统中,包括四个实体型,分别为:
科室:科名,科地址,科电话
病房:病房号,病房地址
医生:工作证号,姓名,职称,年龄
病人:病历号,姓名,性别,主管医生
且存在如下语义约束:
①一个科室有多个病房、多个医生,一个病房只能属于一个科室,一个医生只属于一个科室;
②一个医生可负责多个病人的诊治,一个病人的主管医生只有一个;
③一个病房可入住多个病人,一个病人只能入住在一个病房。
注意:不同科室可能有相同的病房号。
完成如下设计:
(1)画出该医院病房管理系统的E-R图;
(2)将该E-R图转换为关系模型;(要求:1:1和1:n的联系进行合并
(3)指出转换结果中每个关系模式的主码和外码。
(1)E-R图如下
(2)转化后的关系模式如下:
科室(科名,科地址,科电话)
病房(病房号,科名,病房地址)
医生(工作证号,姓名,职称,年龄,科名)
病人(病历号,姓名,性别,主管医生,病房号,科名)
(3)每个关系模式的主码、外码如下:
科室:主码是科名;
病房:主码是病房号,外码是科名;
医生:主码是工作证号,外码是科名;
病人:主码是病历号,外码是科名十病房号。
例题3:
设某商业集团数据库中有三个实体集。
一是“仓库”实体集,属性有仓库号、仓库名和地址等;
二是“商店”实体集,属性有商店号、商店名、地址等;
三是“商品”实体集,属性有商品号、商品名、单价。
仓库与商品之间存在“库存”联系,每个仓库可存储若干种商品,每种商品存储在若干仓库中,库存有个“库存量”、“存入日期”属性;
商店与商品之间存在着“销售”联系,每个商店可销售若干种商品,每种商品可在若干商店里销售,每个商店销售一种商品有月份和月销售量两个属性;
仓库、商店、商品之间存在一个三元联系“供应”,反应了把某个仓库中存储的商品供应到某个商店,此联系有月份和月供应量两个属性。
(1)根据描述,绘制相应的E-R图,并直接在E-R图上注明实体名、属性、联系类型;
(2)将E-R图转换成关系模型,画出相应的数据库模型图,并说明主键和外键。
(1)绘制E-R图
(2)E-R图可转换成6个关系模式:
仓库(仓库号,仓库名,地址)
商品(商品号,商品名,单价)
商店(商店号,商店名,地址)
库存(仓库号,商品号,日期,库存量)
销售(商店号,商品号,月份,月销售量)
供应(仓库号,商店号,商品号,月份,
月供应量)
例题3:
设有如下实体:
学生:学号、单位、姓名、性别、年龄、选修课程名
课程:编号、课程名、开课单位、任课教师号
教师:教师号、姓名、性别、职称、讲授课程编号
单位:单位名称、电话、教师号、教师名
上述实体中存在如下联系:
一个学生可选修多门课程,一门课程可为多个学生选修;
一个教师可讲授多门课程,一门课程可为多个教师讲授;
一个单位可有多个教师,一个教师只能属于一个单位。
试完成如下工作:
(1)分别设计学生选课和教师任课两个局部信息的结构E-R图。
(2)将上述设计完成的E-R图合并成一个全局E-R图。
(1)学生选课局部E-R图
(2)教师任课局部E-R图
(3)合并的全局E-R图
1.1、函数依赖
专业定义:设R(U)是一个属性集U上的关系模式,X和Y是U的子集。若对于R(U)的任意一个可能的关系r,r 中不可能存在两个元组在X上的属性值相等, 而在Y上的属性值不等, 则称“X函数确定Y”或“Y函数依赖于X”,记作X→Y。
案例演示:在关系Student(Sno, Sname, Ssex, Sage, Sdept),假设不允许重名,有:
Sno → Sname
Sno → Ssex
Sno → Sage
Sno → Sdept
Sname → Sno
Sname → Ssex
Sname → Sage
Sname → Sdept
1.2、平凡函数依赖
专业定义:X→Y,但Y⊆X 则称X→Y是平凡的函数依赖。
1.3、非平凡函数依赖
专业定义:X→Y,但Y⊈X则称X→Y是非平凡的函数依赖。
1.4、完全函数依赖
专业定义:
案例演示:在关系SC(Sno, Cno, Grade)中,有:
1.5、部分函数依赖
专业定义:
案例演示:在关系SC(Sno, Cno, Grade)中,则有:
1.6、传递函数依赖
专业定义:
案例演示:在关系Std(Sno, Sdept, Mname)中,有:
Sno → Sdept , Sdept → Mname
6.2、码
2.0、范式
关系数据库中的关系是要满足一定要求都的,满足不同程度要求的不同范式。
2.1、1NF
作为二维表,关系要符合一个最基本的条件:每一个分量必须是不可分开的数据项
。满足了这个条件的关系模式就属于第一范式(1NF)。
2.2、2NF
若关系模式R∈1NF,并且每一个非主属性都完全函数依赖于任何一个候选码,则R∈2NF
。
S-L-C(Sno,Sdept,Sloc,Cno,Grade), Sloc为学生的住处,并且每个系的学生住在同一个地方。S-L-C的码为(Sno,Cno)。函数依赖有:
非主属性Sdept、Sloc并不完全依赖于码,关系模式S-L-C不属于2NF。
一个关系模式不属于2NF,会产生以下问题:
插入异常:如果插入一个新学生,但该生未选课,即该生无Cno,由于插入元组时,必须给定码值,因此插入失败。
删除异常:如果S4只选了一门课C3,现在他不再选这门课,则删除C3后,整个元组的其他信息也被删除了。
修改复杂:如果一个学生选了多门课,则Sdept,Sloc被存储了多次。如果该生转系,则需要修改所有相关的Sdept和Sloc,造成修改的复杂化。
出现这种问题的原因,例子中有两类非主属性:
1.一类如Grade,它对码完全函数依赖。
2.另一类如Sdept、Sloc,它们对码不是完全函数依赖。
解决方法:用投影分解把关系模式S-L-C分解成两个关系模式
SC(Sno,Cno,Grade)
S-L(Sno,Sdept,Sloc)
SC的码为(Sno,Cno)、SL的码为Sno,这样使得非主属性对码都是完全函数依赖了。
2.3、3NF
总结:
第一范式:列不能再分
第二范式: 建立在第一范式基础上,消除部分依赖
第三范式: 建立在第二范式基础上,消除传递依赖。
概念:
存储过程是由过程化SQL语句书写的过程,这个过程经编译和优化后存储在数据库服务器中,因此称它为存储过程。
存储过程的优点
1.执行速度更快
2.减少网络流通量
3.允许模块化程序设计
4.方便实施企业规则
5.提高系统安全性
定义存储过程的语法
--创建存储过程
DELIMITER $ --声明存储过程的结束符
CREATE PROCEDURE stu_test() --存储过程名称(参数列表)
BEGIN --开始
-- 可以写多个sql语句 -- sql语句+流程控制
END $ --结束 结束符
-- 执行存储过程
call stu_test() --call 存储过程名称(参数)
例1:创建存储过程,查看选课数量低于两门的学员名单
1)创建存储过程
delimiter $
create procedure proc_course_less()
begin
select student.sno,sname,count(sc.cno)
from student left join sc on student.sno=sc.sno
group by student.sno
having count(*)<2;
end $
delimiter ;
2)CALL语句用来调用存储过程
call proc_course_less();
drop procedure proc_course_less;
例2:编写存储过程,展示某门课程前N名学生的学号和成绩
delimiter $
create procedure proc_show_top(
IN p_course char(4),
IN p_n INTEGER)
begin
select sno,grade
from sc
where cno=p_course
order by grade desc
limit 0,p_n;
end $
delimiter ;
--调用存储过程
call proc_show_top ('1',3);