ALTER TABLE<表名> ALTERCOLUMN<列名><数据类型>---修改列的定义 ADD<列名><数据类型><约束>---添加新列 DROPCOLUMN<列名>---删除列 ADD [constraint<约束名>]约束定义 ---添加约束 DROP [constraint]<约束名>---删除约束
例 ALTER TABLE Student ADD Spec char(10) NULL//添加专业列,允许为空 ALTER TABLE Student ALTERCOLUMN Spec char(20) //修改专业列类型 ALTER TABLE Student DROPCOLUMN Spec //删除新添加的专业列
实现数据完整性
主键(PRIMARY KEY)约束
1 2 3 4 5 6 7 8
ALTER TABLE 表名 ADD [CONSTRAINT<约束名>]PRIMARY KEY(<列名>[,...n]) 例 ALTER TABLE 雇员 ADD CONSTRAINT PK_EMP PRIMARY KEY (雇员编号) ALTER TABLE 工作 ADD CONSTRAINT PK_JOB PRIMARY KEY (工作编号)
唯一值(UNIQUE)约束
1 2 3 4 5 6
ALTER TABLE 表名 ADD[CONSTRAINT<约束名>]UNIQUE (<列名>[,...n]) 例 ALTER TABLE 雇员 ADD CONSTRAINT UK_SID UNIQUE(电话号码)
SELECT Sname, Sdept, Sage FROM Student WHERE Sage BETWEEN20AND23 //此语句等价于 SELECT Sname, Sdept, Sage FROM Student WHERE Sage >=20AND Sage <=23
查询年龄不在20~23之间的学生姓名,所在系和年龄
1 2 3 4 5
SELECT Sname, Sdept, Sage FROM Student WHERE Sage NOTBETWEEN20AND23 //此语句等价于 SELECT Sname, Sdept, Sage FROM Student WHERE Sage <20OR Sage>23
(确定集合)
查询信息系,数学系和计算机系学生的姓名和性别
1 2 3 4 5
SELECT Sname, Ssex FROM Student WHERE Sdept IN('信息系', '数学系', '计算机系') //此语句等价于 SELECT Sname, Ssex FROM Student WHERE Sdept ='信息系'OR Sdept ='数学系'OR Sdept ='计算机系'
查询既不是信息系,数学系,也不是计算机系学生的姓名和性别
1 2 3 4 5
SELECT Sname, Ssex FROM Student WHERE Sdept NOTIN ('信息系', '数学系', '计算机系') //此语句等价于 SELECT Sname, Ssex FROM Student WHERE Sdept !='信息系'AND Sdept !='数学系'AND Sdept !='计算机系'
(字符串匹配)
_:匹配任意一个字符
%:匹配0个或多个字符
[]:匹配[]中的任意一个字符。对于连续的字母匹配例如[abcd]可写成[a-d]
[^] :不匹配[]中的任意一个字符,对于连续字符[^ abcd 可写成[^a-d
查询姓张的同学的详细信息
1
SELECT*FROM Student WHERE Sname LIKE'张%'
查询学生表中姓张,李,刘的学生的详细信息
1 2 3 4
SELECT*FROM Student WHERE Sname LIKE'[张李刘]%' //或者 SELECT*FROM Student WHERE Sname LIKE'张%'OR Sname LIKE'李%'OR Sname LIKE'刘%'
查询名字中第2个字是小或大的学生的姓名和学号
1
SELECT Sname, Sno FROM Student WHERE Sname LIKE'_[小大]%'
查询所有不姓 “王” 也不姓张” 的学生姓名。
1 2 3 4 5 6
SELECT Sname FROM Student WHERE Sname NOTLIKE'(王|张)'; //或者 SELECT Sname FROM Student WHERE Sname LIKE'[^王张]%'; //或者 SELECT Sname FROM Student WHERE Sname NOTLIKE'王'AND Sname NOTLIKE'张%';
查询姓 “王” 且名字是 2 个字的学生姓名
1
SELECT Sname FROM Student WHERE Sname LIKE'王_'
查询姓 “王” 且名字是 3 个字以内的学生姓名
1
SELECT Sname FROM Student WHERE Sname LIKE'王___'
查询姓 “王” 且名字是 3 个字的学生姓名
1
SELECT Sname FROM Student WHERE RTRIM(Sname) LIKE'王___'
(涉空值的查询)
查询没有考试成绩的学生的学号和相应的课程号
1
SELECT Sno, Cno FROM SC WHERE Grade ISNULL
查询所有有考试成绩的学生的学号和课程号
1
SELECT Sno, Cno FROM SC WHERE Grade ISNOT NULL
(多重条件查询)
查询计算机系年龄在 20 岁以下的学生姓名和年龄
1
SELECT Sname, Sage FROM Student WHERE Sdept='计算机系'AND Sage<20
查询计算机系和信息系年龄大于等于 20 岁的学生姓名、所在系和年龄
1 2 3
SELECT Sname, Sdept, Sage FROM Student WHERE (Sdept='计算机系'OR Sdept='信息系') AND Sage>=20 //也可以写成 SELECT Sname, Sdept, Sage FROM Student WHERE Sdept IN ('计算机系','信息系') AND Sage>=20
对查询结果进行排序
将学生按年龄升序排序
1
SELECT*FROM Student ORDERBY Sage ASC//不写ASC默认升序
查询选修了 “c002” 课程的学生的学号及成绩,查询结果按成绩降序排列
1
SELECT Sno, Grade FROM SC WHERE Cno='c002'ORDERBY Grade DESC
SELECT Sno, COUNT(*)选课门数, AVG(Grade) 平均成绩 FROM SC GROUPBY Sno HAVINGAVG(Grade)>=80
统计每个系的男生人数,只列出男生人数大于等于 2 人的系
1
SELECT Sdept, COUNT(*) 人数 FROM Student WHERE Ssex='男'GROUPBY Sdept HAVINGCOUNT(*)>=2
WHERE、GROUP BY、HAVING 子句的作用及执行顺序
WHERE 子句用来筛选 FROM 子句中指定的数据源所产生的行数据。
GROUP BY 子句用来对经 WHERE 子句筛选后的结果数据进行分组。
HAVING 子句用来对分组后的结果数据再进行筛选。
查询计算机系和信息管理系的学生人数,可以使用如下两种方法
1 2 3 4 5 6 7
SELECT Sdept, COUNT(*) FROM Student GROUPBY Sdept HAVING Sdept IN('计算机系', '信息管理系') //方法二比第一种效率高,因为WHERE子句在GROUPBY 子句之前执行, 因此参与分组的数据会减少 SELECT Sdept, COUNT(*) FROM Student WHERE Sdept IN ('计算机系', '信息管理系') GROUPBY Sdept
多表连接查询
内连接
1
FROM 表 1 [INNER] JOIN 表 2ON<连接条件>
查询每个学生及其选课的详细信息
1
SELECT*FROM Student INNERJOIN SC ON Student.Sno = SC.Sno ---将Student 与SC连接起来
去掉重复列
1
SELECT Student.Sno, Sname, Ssex, Sage, Sdept, Cno, Grade FROM Student JOIN SC ON Student.Sno = SC.Sno
查询计算机系学生修课情况
1 2
SELECT Student.Sno, Sname, Cno, Grade FROM Student JOIN SC ON Student.Sno = SC.Sno WHERE Sdept='计算机系' //也可使用别名写为SELECT Sname, Cno, Grade FROM Student S JOIN SC ON S.Sno = SC.Sno WHERE Sdept='计算机系'
查询 “信息系” 选修 “计算机文化学” 课程的学生成绩
1
SELECT Sname, Cname, Grade FROM Student s JOIN SC ON S.Sno = SC.Sno JOIN Course c ON c.Cno = SC.Cno WHERE Sdept='信息系'AND Cname='计算机文化学'
查询所有选修了 “Java” 课程的学生情况
1
SELECT Sname, Sdept FROM Student S JOIN SC ON S.Sno = SC.Sno JOIN Course C ON C.Cno = SC.Cno WHERE Cname='Java'
有分组的多表连接查询,统计每个系的学生考试平均成绩
1
SELECT Sdept, AVG(grade) as AverageGrade FROM Student S JOIN SC ON S.Sno = SC.Sno GROUPBY Sdept
有分组和行选择条件的多表连接查询,统计计算机系每门课程的选课人数、平均成绩、最高成绩和最低成绩
1
SELECT Cno, COUNT(*) AS Total, AVG(Grade) as AvgGrade, MAX(Grade) as MaxGrade, MIN(Grade) as MinGrade FROM Student S JOIN SC ON S.Sno = SC.Sno WHERE Sdept='计算机系'GROUPBY Cno
自连接
1
FROM 表 1 T1 JOIN 表 1 T2
查询与刘晨在同一个系学习的学生的姓名和所在系
1
SELECT S2.Sname, S2.Sdept FROM Student S1 JOIN Student S2 ON S1.Sdept = S2.Sdept WHERE S1.Sname='刘晨'AND S2.Sname!='刘晨'
查询与 “数据结构” 学分相同的课程的课程名和学分
1
SELECT C1.Cname, C1.Credit FROM Course C1 JOIN Course C2 ON C1.Credit = C2.Credit WHERE C2.Cname='数据结构'
外连接
1
FROM 表 1LEFT|RIGHT [OUTER] JOIN 表 2ON<连接条件>
theta 方式语法格式为左外连接
1
FROM 表 1, 表 2WHERE [表 1.]列名 (+)=[表 2.]列名
右连接
1
FROM 表1, 表2WHERE [表1.] 列名 = [表2.] 列名(+)
使用 LEFT JOIN 和 WHERE 子句进行查询,例如查询没有选课的课程、计算机系没有选课的学生、特定学期的课程选课人数。
使用 TOP 谓词限制结果集,可指定取前 n 行数据或前 n% 行数据,还可以使用 WITH TIES 包括并列结果,TOP 谓词写在 SELECT 单词后边(如果有 DISTINCT,则在 DISTINCT 之后),查询列表的前边。
在 TOP 子句中使用 WITH TIES 谓词时,要求必须使用 ORDER BY 子句对查询结果进行排序,否则会出现语法错误。最好同时使用 TOP 谓词与 ORDER BY 子句。
-- 查询没有选课的课程名称 SELECT Cname FROM Course C LEFTJOIN SC ON C.Cno = SC.Cno WHERE SC.Cno ISNULL;
-- 查询计算机系没有选课的学生姓名和性别 SELECT Sname, Ssex FROM Student LEFTOUTERJOIN SC ON Student.Sno = SC.Sno WHERE SC.Sno ISNULLAND Sdept='计算机系';
-- 统计第 2~4 学期开设的课程中每门课程的选课人数,包括没有人选的课程 SELECT C.Cno 课程号, COUNT(SC.Cno) 选课人数 FROM Course C LEFTOUTERJOIN SC ON C.Cno = SC.Cno WHERE Semester IN(2,3,4) GROUPBY C.Cno;
-- 查询年龄最大的三名学生的姓名、年龄及所在系 SELECT TOP 3 Sname, Sage, Sdept FROM Student ORDERBY Sage DESC;
-- 查询年龄最大的三名学生的姓名、年龄及所在系,包括并列情况 SELECT TOP 3WITH TIES Sname, Sage, Sdept FROM Student ORDERBY Sage DESC;
-- 查询 Java 课程考试成绩前三名的学生的姓名、所在系和成绩,包括并列情况 SELECT TOP 3WITH TIES Sname, Sdept, Grade FROM Student S JOIN SC on S.Sno = SC.Sno JOIN Course C ON C.Cno = SC.Cno WHERE Cname ='Java'ORDERBY Grade DESC;
-- 查询选课人数最多的前两门课程(包括并列情况),列出课程号和选课人数 SELECT TOP 2WITH TIES C.Cno 课程号, COUNT(*) 选课人数 FROM Course C JOIN SC ON C.Cno = SC.Cno GROUPBY C.Cno ORDERBYCOUNT(*) DESC;
子查询
子查询概念:一个 SELECT 语句嵌套在另一个 SELECT、INSERT、UPDATE 或 DELETE 语句中称为子查询,子查询通常写在圆括号中,可出现在任何能使用表达式的地方,一般用于外层查询的 WHERE 子句或 HAVING 子句中构成查询条件。
使用子查询进行基于集合的测试:通过运算符 IN 或 NOT IN 将一个表达式的值与子查询返回的结果集进行比较,形式为 WHERE 表达式 [NOT] IN (子查询),先执行子查询,再基于子查询结果执行外层查询,子查询返回的结果是一个集合,外层查询在这个集合上使用 IN 运算符进行比较,且子查询返回结果集中的列的个数、数据类型以及语义必须与表达式中的相同。
1 2 3 4 5
-- 查询与“刘晨”在同一个系学习的学生 SELECT Sno, Sname, Sdept FROM Student WHERE Sdept IN (SELECT Sdept FROM Student WHERE Sname ='刘晨');
-- 查询与“刘晨”在同一个系学习的学生且不包含“刘晨” SELECT Sno, Sname, Sdept FROM Student WHERE Sdept IN (SELECT Sdept FROM Student WHERE Sname ='刘晨') AND Sname!='刘晨';
使用子查询进行比较测试,语法格式为 WHERE 表达式比较运算符 (子查询),要求子查询语句必须是返回单值的查询语句,对于要与聚合函数进行比较的查询应使用这种子查询实现,同样是先执行子查询,再根据子查询返回的结果执行外层查询。
1 2 3 4 5 6 7 8 9 10 11
-- 查询考试成绩大于 90 分的学生的学号和姓名 SELECT Sno, Sname FROM Student WHERE Sno IN (SELECT Sno FROM SC WHERE Grade>90);
-- 查询选修了 Java 课程的学生的学号和姓名 SELECT Sno, Sname FROM Student WHERE Sno IN (SELECT Sno FROM SC WHERE Cno IN (SELECT Cno FROM Course WHERE Cname='Java'));
-- 统计选修了 Java 课程的这些学生的选课门数和平均成绩 SELECT Sno 学号, COUNT(*) 选课门数, AVG(Grade) 平均成绩 FROM SC WHERE Sno IN (SELECT Sno FROM SC JOIN Course C ON C.Cno = SC.Cno WHERE Cname='Java') GROUPBY Sno;
-- 查询选了“c005”课程且考试成绩高于此课程的平均成绩的学生的学号和成绩 SELECT Sno, Grade FROM SC WHERE Cno='c005'AND Grade>(SELECTAVG(Grade) FROM SC WHERE Cno ='c005');
-- 查询计算机系年龄最大的学生的姓名和年龄(使用 TOP 子句实现) SELECT TOP 1WITH TIES Sname, Sage FROM Student WHERE Sdept='计算机系'ORDERBY Sage DESC;
-- 查询 Java 考试成绩高于 Java 平均成绩的学生的姓名、所在系和 Java 成绩(多表连接和子查询混合) SELECT Sname, Sdept, Grade FROM Student S JOIN SC ON S.Sno = SC.Sno JOIN Course C ON C.Cno = SC.Cno WHERE Cname ='Java'AND Grade > (SELECTAVG(Grade) FROM SC JOIN Course CON C.Cno = SC.Cno WHERE Cname ='Java');
-- 查询选了“c001”课程的学生姓名(多表连接方式) SELECT Sname FROM Student JOIN SC ON SC.Sno = Student.Sno WHERE Cno='c001'; -- 查询选了“c001”课程的学生姓名(子查询方式) SELECT Sname FROM Student WHERE Sno IN (SELECT Sno FROM SC WHERE Cno='c001'); -- 查询选了“c001”课程的学生姓名(带 EXISTS 谓词方式) SELECT Sname FROM Student WHEREEXISTS (SELECT*FROM SC WHERE Sno = Student.Sno AND Cno='c001');
-- 删除所有不及格学生的选课记录(基于本表) DELETEFROM SC WHERE Grade <60; -- 删除所有不及格学生的选课记录(用多表连接实现) DELETEFROM SC FROM SC JOIN Student ON SC.Sno = Student.Sno WHERE Sdept='计算机系'AND Grade <60 -- 删除所有不及格学生的选课记录(用子查询实现) DELETEFROM SC WHERE Grade <60AND Sno IN (SELECT Sno FROM Student WHERE Sdept ='计算机系')
数据查询
将查询结果保存到新表中
1 2 3 4 5 6 7 8 9 10 11 12 13
SELECT 查询列表序列 INTO<新表名>FROM 数据源 -- 其他行选择、分组等语句
-- 查询计算机系学生的姓名、选的课程名和成绩,并将查询结果保存到永久表S_C_G中。 SELECT Sname, Cname, Grade INTO S_C_G FROM Students JOIN SC ON s.Sno = SC.Sno JOIN Course c ON c.Cno = SC.Cno WHERE Sdept ='计算机系';
-- 统计每个系的学生人数,并将结果保存到永久表dept_cnt中。 SELECT Sdept, COUNT(*) AS 人数 INTO dept_cnt FROM Student GROUPBY Sdept;
-- 查询选修 Java 课程的学生的学号、姓名、所在系和成绩,并对所在系进行如下处理:当所在系为 “计算机系” 时,在查询结果中显示 “CS”;当所在系为 “信息系” 时,在查询结果中显示 “IS”;当所在系为 “数学系” 时,在查询结果中显示 “MA” SELECT s.Sno学号,Sname姓名, CASE WHEN Sdept ='计算机系'THEN'CS' WHEN Sdept ='信息系'THEN'IS' WHEN Sdept ='数学系'THEN'MA' ENDAS所在系,Grade成绩 FROM Students s JOIN SC ON s.Sno = SC.Sno JOIN Course c ON c.Cno = SC.Cno WHERE Cname ='Java'
-- 并运算(UNION)示例--查询李勇和刘晨所选的全部课程,列出课程名、学期和开课学期。 SELECT Cname, Semester, SemesterFrom FROM Course C JOIN SC ON C.Cno = SC.Cno JOIN Student S ON S.Sno = SC.Sno WHERE Sname ='李勇' UNION SELECT Cname, Semester, SemesterFrom FROM Course C JOIN SC ON C.Cno = SC.Cno JOIN Student S ON S.Sno = SC.Sno WHERE Sname ='刘晨' -- (交运算):查询李勇和刘晨所选的相同的课程(即同时被李勇和刘晨选中的课程),列出课程名和学分。 SELECT Cname, Credit FROM Student JOIN SC ON S.Sno = SC.Sno JOIN Course C ON C.Cno = SC.Cno WHERE Sname ='李勇' INTERSECT SELECT Cname, Credit FROM Student JOIN SC ON S.Sno = SC.Sno JOIN Course C ON C.Cno = SC.Cno WHERE Sname ='刘晨' -- (差运算):题目:查询李勇选了但刘晨没有选的课程的课程名和开课学期。 SELECT C.Cno, Cname, SemesterFrom FROM Course C JOIN SC ON C.Cno = SC.Cno JOIN Student S ON S.Sno = SC.Sno WHERE Sname ='李勇' EXCEPT SELECT C.Cno, Cname, SemesterFrom FROM Course C JOIN SC ON C.Cno = SC.Cno JOIN Student S ON S.Sno = SC.Sno WHERE Sname ='刘晨'