SQL Server数据库查询

本文详细介绍SQL语言中的查询操作,包括基本的SELECT语法、条件筛选、排序、分组、连接查询、嵌套查询等内容,并提供了丰富的实例帮助理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、SELECT语法
    SELECT select_list
    [INTO new_table_name ]
    FROM table_list
    [ WHERE search_conditions ]
    [ GROUP BY group_by_list ]
    [ HAVING search_conditions ]
    [ ORDER BY order_list [ ASC | DESC ] ]

2、选择表中的若干列
(1)查询指定列
例1:查询全体学生的学号和姓名
SELECT Sno, Sname FROM Student

例2:查询全体学生的姓名、学号、所在系,查询结果列改名
SELECT Sname AS 姓名, Sno 学号, 所在系 = Sdept FROM Student

(2)查询全部列
例3:查询Student表的全部列
SELECT * FROM Student

(3)查询经过计算的列
例4:查询全体学生的姓名及其出生年份
--GETDATE():得到系统的当前日期;YEAR():得到指定日期的年号。
SELECT Sname, YEAR(GETDATE()) – Sage AS 出生年份
FROM Student

3、选择表中的若干元组
(1)取消重复元组
使用DISTINCT短语,可以让相同的元组只显示一个
例5: 查询选修了课程的学生学号

SELECT Sno FROM SC

(2)比较大小
查询满足条件的元组:查询满足指定条件的元组可以通过WHERE子句实现;

例6:查询计算机系全体学生的名单

SELECT Sname FROM Student WHERE Sdept = 'CS'

例7:查询所有年龄在20岁以下的学生姓名及其年龄
SELECT Sname, Sage FROM Student WHERE Sage < 20

例8: 查询考试成绩有不及格的学生的学号
SELECT DISTINCT Sno FROM SC WHERE Grade < 60

(2)确定范围
例9: 查询年龄在20至23岁之间的学生的姓名、系别、和年龄
SELECT Sname, Sdept, Sage FROM Student WHERE Sage BETWEEN 20 AND 23
SELECT Sname, Sdept, Sage FROM Student WHERE Sage >= 20 AND Sage <= 23

例10: 查询年龄不在20至23岁之间的学生的姓名、系别、和年龄
SELECT Sname, Sdept,Sage FROM Student WHERE Sage NOT BETWEEN 20 AND 23
SELECT Sname, Sdept, Sage FROM Student WHERE Sage < 20 OR Sage > 23

(3)确定集合
例11: 查询信息系(IS)和计算机科学系(CS)的学生的姓名和性别
SELECT Sname, Ssex FROM Student WHERE Sdept IN('IS', 'CS')

例12: 查询既不是信息系(IS),也不是计算机系(CS)的学生的姓名和性别
SELECT Sname, Ssex FROM Student WHERE Sdept NOT IN('IS', 'CS')

(4)字符匹配
谓词LIKE用来进行全部或部分字符串匹配。
在进行部分字符串匹配时要用通配符“%”和“_”,
“%”匹配0个或多个字符,
“_”匹配1个字符,查询时使用LIKE和通配符,可以实现模糊查询。

例13:查询学号为2017001的学生的情况
--注:若LIKE后面的匹配串不含通配时,则可以用“=”运算符取代谓词LIKE。
SELECT * FROM Student WHERE Sno LIKE '2017001'
SELECT * FROM Student WHERE Sno = '2017001'

例14:查询所有姓“刘”的学生的姓名、学号和性别
SELECT Sname, Sno, Ssex FROM Student
WHERE Sname LIKE '刘%'

例15: 查询所有不姓“刘”的学生姓名
SELECT Sname FROM Student WHERE Sname NOT LIKE '刘%'

例16:查询名字中第二字为“桃”字的学生的姓名和学号
SELECT Sname, Sno FROM Student
WHERE Sname LIKE '_桃%'

例17:查找姓氏在李与王之间的学生信息
SELECT * FROM Student
WHERE Sname LIKE '[李-王]%'

例18:查询DB_Design课程的课程号和学分
通过ESCAPE指定“\”字符是一个转义字符。
SELECT Cno, Ccredit FROM Course
WHERE Cname LIKE 'DB\_Design' ESCAPE '\'

(5)涉及空值的查询
例19:查询选修了课程但没有成绩的学生学号和课程号
SELECT Sno, Cno FROM SC
WHERE Grade IS NULL

例20:查询所有有成绩的学生学号和课程号
SELECT Sno, Cno FROM SC
WHERE Grade IS NOT NULL

(6)多重条件查询
使用逻辑运算符AND和OR来联结多个查询条件,AND的优先级高于OR。

例21:查询CS系年龄在20岁以下的学生姓名
SELECT Sname, Ssex FROM Student
WHERE Sdept = 'CS' AND Sage < 20

扩展:SQL注入
用户名:' OR 1=1 --'
密  码:随意
SELECT COUNT(*) FROM Users
WHERE userName = '' OR 1=1 --'' and userPwd = 'AA'

用户名:随意
密  码:' OR ''='
SELECT COUNT(*) FROM Users
WHERE userName = 'AA' and userPwd = '' or ''=''

4、对查询结果排序
如果没有指定查询结果的显示顺序,DBMS将按其最方便的顺序(通常是元组在数据表中的先后顺序)输出查询结果;
用户也可以用ORDER BY子句指定按照一个或多个属性列的升序(ASC)或降序(DESC)重新排列查询结果,其中升序ASC为缺省值;

例22:查询选修了3号课程的学生的学号及其成绩,查询结果按分数的降序排列
SELECT Sno, Grade FROM SC
WHERE Cno = '3'
ORDER BY Grade DESC

例23:查询全体学生情况,查询结果按所在系升序排列,对同一系中的学生按年龄降序排列
SELECT * FROM Student
ORDER BY Sdept, Sage DESC

5、使用集函数
SQL提供了许多集函数,主要包括:SUM、COUNT、MAX、MIN、AVG。

例24:查询学生总人数
SELECT COUNT(*) FROM Student

例25:查询选修了课程的学生人数
SELECT COUNT(DISTINCT Sno) FROM SC

例26:计算1号课程的学生平均成绩
SELECT AVG(Grade) FROM SC
WHERE Cno = '1'

例27: 查询学习1号课程的学生最高分数
SELECT MAX(Grade) FROM SC
WHERE Cno = '1'

6、对查询结果分组
GROUP BY子句可以将查询结果表的各行按一列或多列值分组,值相等的为一组。
对查询结果分组的目的是为了细化集函数的作用对象。
如果未对查询结果分组,集函数将作用于整个查询结果,即整个查询结果只有一个函数值。否则,集函数将作用于每一个组,即每一组都有一个函数值。
WHERE子句与HAVING短语的区别在于作用对象不同。WHERE子句作用于基本表或视图,从中选择满足条件的元组。HAVING短语作用于组,从中选择满足条件的组。

例28:查询各个课程号与相应的选课人数
SELECT Cno, COUNT(Sno) FROM SC
GROUP BY Cno

例29:查询选修了2门以上课程的学生的学号
先用GROUP BY子句按Sno分组,再用集函数COUNT对每一组计数。HAVING短语指定选择组的条件,只有满足条件(即元组个数>3,表示此学生选修的课超过3门)的组才会被选出来。
SELECT Sno FROM SC
GROUP BY Sno
HAVING COUNT(*) > 2

三、连接查询
若一个查询同时涉及两个以上的表,则称之为连接查询;
连接查询主要包括:① 等值连接、非等值连接查询;② 自身连接查询;③ 外连接查询;④ 复合条件连接查询;

1、等值与非等值连接
例30:查询每个学生及其选修课程的情况
SELECT Student.*, SC.* FROM Student, SC
WHERE Student.Sno = SC.Sno
等价于:
SELECT Student.*, SC.*
FROM Student INNER JOIN SC ON Student.Sno = SC.Sno

例31:自然连接Student和SC表
若属性列在两个表中是唯一的,可以省略表名前缀。
SELECT Student.Sno, Sname, Ssex, Sage, Sdept, Cno, Grade
FROM Student, SC WHERE Student.Sno = SC.Sno

2、自身连接
例32:查询每一门课的间接先修课(即先修课的先修课)
SELECT A.Cno, B.Cpno
FROM Course A, Course B
WHERE A.Cpno = B.Cno

3、外连接
内连接 INNER JOIN:结果集仅包含那些满足连接条件的数据行;使用INNER JOIN 连接运算符,使用ON 关键字指定连接条件。
左外连接 LEFT [OUTER] JOIN:左外连接对连接条件中左边的表不加限制;
右外连接 RIGHT [OUTER] JOIN:右外连接对连接条件中右边的表不加限制;
全外连接 FULL [OUTER] JOIN:全外连接对两个表都不加限制,所有两个表中的行都会包括在结果集中;
交叉连接 CROSS JOIN:称为笛卡尔成绩,返回两个表的乘积,结果集中包含了所连接的两个表中所有行的全部组合;

例33:查询所有选修了1号的学生的姓名、课程号和成绩
SELECT Sname, Cno, Grade
FROM Student, SC
WHERE Student.Sno = SC.Sno AND Cno = '1'

--或者
SELECT Sname, Cno, Grade
FROM Student INNER JOIN SC
ON Student.Sno = SC.Sno AND Cno = '1'

例34:查询每个学生及其选修课程的情况(即使没有选课也列出该学生的基本情况)
SELECT Student.Sno, Sname, Ssex, Sage, Sdept, Cno, Grade
FROM Student LEFT JOIN SC
ON Student.Sno = SC.Sno

比较下面两条语句的区别
SELECT Student.Sno, Sname, Ssex, Sage, Sdept, Cno, Grade
FROM Student LEFT JOIN SC
ON Student.Sno = SC.Sno AND Cno = '1'
比较:
SELECT Student.Sno, Sname, Ssex, Sage, Sdept, Cno, Grade
FROM Student LEFT JOIN SC
ON Student.Sno = SC.Sno
WHERE Cno = '1'

例35:全外连接。查询每个学生及其选修课程的信息,包含未选课的学生 信息及未被选修的课程信息
SELECT Student.Sno, Sname, Course.Cno, Cpno, Ccredit, Cname, Grade
FROM Course FULL JOIN SC ON Course.Cno = SC.Cno
FULL JOIN Student ON Student.Sno = SC.Sno

4、复合条件连接
例36:查询选修2号课程且成绩在85分以上的所有学生
SELECT Student.Sno, Sname
FROM Student, SC
WHERE Student.Sno = SC.Sno AND Cno = '2' AND Grade > 85

例37:查询每个学生及其选修的课程名及其成绩
SELECT Student.Sno, Sname, Cname, Grade
FROM Student, Course, SC
WHERE Student.Sno = SC.Sno AND Course.Cno = SC.Cno

四、嵌套查询
在SQL语言中,一个SELECT-FROM-WHERE语句称为一个查询块。
将一个查询块嵌套在另一个查询块的WHERE子句或HAVING短语的条件中的查询称为嵌套查询或子查询。

1、无关子查询
子查询的执行不依赖于外部查询;
子查询在外部查询之前执行,然后返回数据提供给外部查询使用;
子查询中不包含对于外部查询的任何引用;
子查询的SELECT 语句中不能使用ORDER BY子句,ORDER BY子句只能对最终查询结果进行排序;

例38:查询与“刘晨”在同一个系学习的学生
SELECT * FROM Student
WHERE Sdept IN (SELECT Sdept FROM Student WHERE Sname = '刘晨')

--注:“=”只能用于查询结果中只有一个元组的情况
SELECT * FROM Student
WHERE Sdept = (SELECT Sdept FROM Student WHERE Sname = '刘晨')

例39:查询选修了课程名为“信息系统”的学生学号和姓名
SELECT Sno, Sname FROM Student WHERE Sno IN(
   SELECT Sno FROM SC WHERE Cno IN(
      SELECT Cno FROM Course WHERE Cname = '信息系统'
   )
)

例40:查询所有未修1号课程的学生姓名
SELECT Sname FROM Student
WHERE Sno NOT IN(
   SELECT Sno FROM SC WHERE Cno = '1'
)

2、相关子查询
子查询的执行依赖于外部查询,多数情况下是子查询的 WHERE 子句中引用了外部查询的表;
子查询的执行过程:(1)子查询为外部查询的每一行执行一次,外部查询将子查询引用的列的值传给子查询;(2)如果子查询的任何行与其匹配,外部查询就返回结果行;(3)再回到第一步,直到处理完外部表的每一行。

例41:查询成绩比该课的平均成绩低得学生的学号,课程号和成绩
SELECT Sno, Cno, Grade FROM SC A
WHERE Grade < (SELECT AVG(Grade) FROM SC B WHERE A.Cno = B.Cno)

例42:查询所有选修了1号课程的学生姓名
带有EXISTS谓词的子查询不返回任何实际数据,它只产生逻辑真值“true”或逻辑假值“false”。
SELECT Sname FROM Student WHERE EXISTS(
SELECT * FROM SC WHERE Sno = Student.Sno and Cno = '1')

或者
SELECT Sname FROM Student WHERE Sno IN(
   SELECT Sno FROM SC WHERE Cno = '1'
)

或者
SELECT Sname FROM Student, SC
WHERE Student.Sno = SC.Sno AND SC.Cno = '1'

例43:查询所有未修1号课程的学生姓名
--用带IN谓词的子查询
SELECT Sname FROM Student WHERE Sno NOT IN(
   SELECT Sno FROM SC WHERE Cno = '1'
)
--用带EXISTS谓词的子查询
SELECT Sname FROM Student WHERE NOT EXISTS(
  SELECT * FROM SC WHERE SC.Sno = Student.Sno AND Cno = '1'
)

例44:查询选修了全部课程的学生姓名
SELECT Sname FROM Student WHERE NOT EXISTS(
    SELECT * FROM Course WHERE NOT EXISTS(
       SELECT * FROM SC WHERE Cno = Course.Cno
AND Sno = Student.Sno
    )
)

五、集合查询
1、并UNION
例45:查询计算机科学系的学生及年龄小于19岁的学生
SELECT * FROM Student WHERE Sdept = 'CS'
UNION
SELECT * FROM Student WHERE Sage < 19

2、交INTERSECT
例46:查询计算机科学系年龄小于19岁的学生
SELECT * FROM Student WHERE Sdept = 'CS'
INTERSECT
SELECT * FROM Student WHERE Sage < 19

3、差EXCEPT
例47:查询计算机科学系年龄大于19岁的学生
SELECT * FROM Student WHERE Sdept = 'CS'
EXCEPT
SELECT * FROM Student WHERE Sage < 19

六、数据更新
1、插入数据
(1)插入一个元组
例48:将一个新学生记录(学号:2017007;姓名:王桃群;性别:女;所在系:CS;年龄:18岁)插入Student表中
INSERT INTO Student VALUES('2017007', '王桃群', '女', 'CS', 18)

例49:插入一条选课记录('2017007 ', '1')
INSERT INTO SC(Sno, Cno) VALUES('2017007', '1')
--或者
INSERT INTO SC VALUES('2017007', '1', NULL)(2)插入多个元组

例50:将每个系学生的平均年龄插入到DeptAge表中
--方法1:先创建DeptAvgAge表
CREATE TABLE DeptAvgAge(
   Sdept CHAR(2),
   AvgAge INT
)
INSERT INTO DeptAvgAge
SELECT Sdept, AVG(Sage)
FROM Student
GROUP BY Sdept

--方法2:不必先创建DeptAvgAge表
SELECT Sdept, AVG(Sage) AvgAge
INTO DeptAvgAge
FROM Student GROUP BY Sdept

比较下面语句的作用
SELECT  * INTO  TABLE2 FROM  TABLE2 WHERE 1 = 2
INSERT TABLE2 SELECT * FROM TABLE1
SELECT  * INTO  TABLE2 FROM TABLE1

2、修改数据
例51:将学生2017007的年龄改为22岁
UPDATE Student
SET Sge = 22
WHERE Sno = '2017007'

例52:将计算机科学系全体学生的成绩置0
--方法1
UPDATE SC
SET Grade = 0
WHERE Sno IN(
  SELECT Sno
    FROM Student
    WHERE Sdept = 'CS')

--方法2:
UPDATE SC
SET Grade = 0
FROM Student JOIN SC
ON Student.Sno = SC.Sno and Sdept = 'CS'

--方法3
UPDATE SC
SET Grade = 50
FROM Student,  SC
WHERE Student.Sno = SC.Sno and Sdept = 'CS'

3、删除数据
例53:删除所有成绩不及格的选课记录
DELETE FROM SC WHERE Grade < 60

例54:删除所有的选课记录
DETELE FROM SC
--或者
TRUNCATE TABLE SC

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值