8.5 关系数据库标准语言SQL
8.5.1SQL 概述
结构化查询语言(Structured Query Language,SQL )是目前使用最广泛的关系数据库的标准查询语言。SQL 具有以下特点。
1.一体化
SQL 是一种一体化的语言,它包括数据定义、数据查询、数据操纵和数据控制等多方面的功能,可完成数据库活动中的全部工作。SQL 同时集成了数据定义语言、数据操纵语言和数据控制语言。
2.高度非过程化
SQL 是高度非过程化语言。 在进行数据操作时,只要用户指出“做什么”,而不必指明“怎么做”,具体的实现则是数据库管理系统的任务。
3.面向集合的操作方式
SQL 语言采用的是集合操作方式,其操作对象和结果都可以是元组的集合。
4.多种使用方式
SQL 既是自含式语言,又是嵌入式语言。
作为自含式语言,它能够独立地用于联机交互,用户可以在终端键盘上直接键入SQL 命令对数据库进行操作。 作为嵌入式语言,SQL 能够嵌入到高级语言(如C、VB)程序中,供程序员设计程序时使用。 而在两种使用方式下,SQL 的语法结构基本上是一致的。 这种以统一的语法结构提供两种使用方式的做法,为用户提供了极大的灵活性与方便性。
5.语言简洁,易学易用
SQL 语言非常简洁,完成其核心功能只用到了九个动词:数据定义(CREATE、DROP、ALTER)、数据查询(SELECT)、数据操纵(INSERT、UPDATE、DELETE)、数据控制(GRANT、REVOKE)。SQL 接近英语口语,因此容易学习,容易使用。
8.5.2SQL 数据查询语句
数据查询语句SELECT-SQL 是SQL 的核心语句,具有强大的查询功能,熟练掌握SELECT-SQL 语句的一部分就可以实现大部分的数据库查询工作。
SELECT语句常用格式如下:
SELECT[ALL|DISTINCT] 〈列名表〉
FROM〈表名〉 [,〈表名〉]
[WHERE〈条件表达式〉]
[GROUP BY〈列名表〉 [HAVING〈条件表达式〉]]
[ORDER BY〈列名表〉 [ASC|DESC]...]
说明:
(1)SELECT子句指明要显示的字段。 选项DISTINCT将删除所选字段的重复记录,默认为ALL,即允许重复数据集合出现。
(2)FROM子句指定了表名,表中包含了SELECT子句所指定的字段。
(3)WHERE子句指明了筛选条件,用于选择满足条件的记录。
(4)GROUP子句将结果按〈列名表〉的值进行分组,该属性列值相等的元组为一个组,每个组产生结果表中的一条记录。 通常,在每组中作用聚集函数。 若带HAVING短语,则只有满足指定条件的组才输出。
(5)ORDER子句将结果按〈列名表〉的值升序或降序排列,选项ASC为升序, DESC为降序,默认为升序。
8.5.3 SELECT语句的应用示例
下面以6.2.2中的教学管理数据库为例,说明SELECT如何实现简单查询、条件查询和自然连接查询等。
1.简单查询
(1)查询所有列
例8.4:查询“学生”表中所有的字段信息。
SELECT*
FROM学生;
(2)查询指定列
例8.5:查询“学生”表中所有学生的“姓名”“性别”“生源”和“政治面貌”信息。
SELECT姓名,性别,生源,政治面貌
FROM学生;
(3)查询计算列的值
例8.6:查询“教师”表中所有教师的“教师编号”“姓名”“职称”“工资”和“纳税金额”[假设纳税金额=(工资-2000)*5%)]信息。
SELECT教师编号,姓名,职称,工资,(工资-2000)*0.05AS纳税金额
FROM教师;
说明:使用AS为返回结果指定
别名。
(4)查询指定列的唯一值
例8.7:查询“学生”表中所有的“生源”地(重复值只保留一个)。
SELECT DISTINCT生源
FROM学生;
2.条件查询
在SELECT-SQL 语句中使用WHERE子句设置查询数据的筛选条件。
(1)使用比较运算符
例8.8:查询“学生”表中所有生源地非“福建”的学生的姓名和性别。
SELECT姓名,性别
FROM学生
WHERE生源〈〉“福建“;
说明:SQL 中使用的比较运算符有=(等于)、〈(小于)、〉(大于)、〉=(大于等于)、〈=(小于等于)、〈〉(不等于)。
(2)使用逻辑运算符
例8.9:查询“学生”表中1998年出生的男生的“学号”“姓名”“性别”和“出生日期”信息。
SELECT学号,姓名,性别,出生日期
FROM学生
WHERE性别=“男“ANDYear(出生日期)=1998;
说明:本例使用了求年份函数year(日期)。
例8.10:查询“学生”表中所有“团员”和“党员”的“姓名”“性别”“出生日期”和“政治面貌”信息。
SELECT姓名,性别,出生日期,政治面貌
FROM学生
WHERE政治面貌=“党员“Or政治面貌=“团员“;
例8.11:查询“学生”表中所有“团员”和“党员”且性别为男的“姓名”“性别”“出生日期”和“政治面貌”信息。
SELECT姓名,性别,出生日期,政治面貌
FROM学生
WHERE(政治面貌=“党员“Or政治面貌=“团员“) And性别=“男“;
说明:SQL 中使用的逻辑运算符有AND(与)、OR(或)、NOT(非)。
(3)使用LIKE运算符
LIKE运算符为字符串匹配运算符,可对字符型数据进行模糊匹配。
其使用格式如下:
〈列名〉[NOT] LIKE“〈字符串常量〉“
字符串常量中除了可含有普通字符以外,还可包含以下两个通配符。
*:表示任意多个字符或汉字。
?:表示任意一个字符或汉字。
NOTLIKE是LIKE的否定运算。
例8.12:查询“学生”表中所有姓名中含有“龙”的学生信息。
SELECT*
FROM学生
WHERE姓名Like“*龙*“;
例8.13:查询“学生”表中“学号”字段第4、5位是“23”的学生的“姓名”“性别”“出生日期”和“生源”信息。
SELECT学号,姓名,性别,出生日期,生源
FROM学生
WHERE学号Like“23*“;
(4)使用BETWEEN运算符
BETWEEN运算符为区间运算符,表示介于两个值之间。
其格式如下:
〈列名〉[NOT] BETWEEN〈值1〉AND〈值2〉
NOTBETWEEN是BETWEEN的否定运算。
例8.14:查询“学生”表中1997~1998年出生的学生的“姓名”“性别”“出生日期”和“生源”信息。
SELECT姓名,性别,出生日期,生源
FROM学生
WHERE出生日期Between#1/1/1997#And#12/31/1998#;
说明:日期前后要加上“#”;使用BETWEEN时应包括边界值,上述条件等价于
出生日期〉=#1/1/1997#And出生日期〈=#12/31/1998#。
(5)使用IN运算符
IN运算符是成员判断运算符,判断指定值是否在指定的值的集合中。
其格式如下:
〈列名〉[NOT] IN(〈值1〉, 〈值2〉,…, 〈值n〉)
NOTIN是IN的否定运算。
例8.15:查询“学生”表中所有“团员”和“党员”的学生信息。
SELECT*
FROM学生
WHERE政治面貌In(“党员“,“团员“);
(6)使用ISNULL
ISNULL是空值判断运算符,用于检查是否为NULL。 ISNOTNULL是ISNULL的否定运算。
例8.16:假设“成绩”表未考试科目的“成绩”字段值为NULL,查询已考试科目的课程号且课程号不重复。
SELECTDISTINCT课程号
FROM成绩
WHERE成绩Is Not Null;
说明:条件不可写成“列名=NULL”;NULL就是空,ISNULL或ISNOTNULL可用于任何类型的字段;空值表示未知值,不等同于“空字符串”和数值0。
3.统计查询
利用SQL 的统计函数对字段进行求和、平均值、最大值、最小值或计算相关运算,输出列为统计函数的返回值。SQL 的常用统计函数如表8-1所示。
表8-1SQL 的常用统计函数
例8.17:查询并统计“成绩”表中课程号为“101”的课程的最高分、最低分和平均分。
SELECTMax(成绩) AS最高分,Min(成绩) AS最低分,Avg(成绩) AS平均分
FROM成绩
WHERE课程号=“101“;
4.自然连接查询
自然连接是一种特殊的等值连接,要求两个关系表中进行比较的必须是相同的属性列,在结果中消除重复的属性列。
例8.18:查询成绩在60与80分之间(含60分与80分)的所有学生的“学号”“姓名”“课程号”及“成绩”。
SELECT学生.学号,姓名,课程号,成绩
FROM学生,成绩
WHERE学生.学号 =成绩.学号And成绩〉=60And成绩〈=80;
说明:学号字段同时存在“学生”表和“成绩”表中,在学号字段前必须加上表名作为前缀,以标识是哪一个表的学号;而其他几个字段是唯一的,故可省略各自的前缀。
5.分组查询
GROUPBY子句通常和聚集函数一起使用,用来对查询结果进行分组,目的是细化聚集函数的作用对象。 分组聚集函数作用于每个组。
例8.19:查询并统计“成绩”表中各门课程的最高分、最低分和平均分。
SELECT课程号,MAX(成绩) AS最高分,MIN(成绩) AS最低分,AVG(成绩) AS平均分
FROM成绩
GROUPBY课程号;
例8.20:查询并统计“教师”表中各职称的男女教师的人数。
SELECT职称,性别,Count(*) AS人数
FROM教师
GROUPBY职称,性别;
例8.21:查询并统计“教师”表中各职称的男教师的人数,仅要求输出人数大于等于5的信息。
SELECT职称,COUNT(*) AS人数
FROM教师
WHERE性别=“男“
GROUPBY职称HAVINGCOUNT(*)〉=5;
说明:SELECT子句中的列名表项,要么是统计函数,要么必须出现在GROUPBY子句中。 当有多个分组依据时,各分组依据之间用逗号隔开。 HAVING子句不同于WHERE子句,它是对分组结果进行筛选。 WHERE子句是指定哪些记录能够参与统计,而HAVING子句指定的是分组后作为查询结果输出的条件。
6.排序
在SELECT-SQL 语句中使用ORDERBY子句,可使查询结果按一定的顺序显示。
例8.22:查询“成绩”表中所有选修课程的学生的“学号”“课程号”和“成绩”信息,并按“学号”升序排列,“学号”相同的再按“成绩”降序排列。
SELECT学号,课程号,成绩
FROM成绩
ORDERBY学号,成绩DESC;
8.5.4SQL 数据更新语句
SQL 数据更新操作有三种:添加记录、修改记录和删除记录,分别由INSERT、UP-DATE和DELETE语句实现。
1.添加记录
格式:INSERTINTO〈表名〉[(〈列名1〉[,〈列名2〉[,)]]
VALUES(〈常量1〉[,〈常量2〉[,)];
功能:将新记录添加到指定〈表名〉中。 其中,新记录的〈列名1〉的值为〈常量1〉,〈列名2〉的值为〈常量2〉,以此类推。 INTO子句中没有出现的列,新记录在这些列(字段)上将取空值。 但必须注意:如果表定义时说明了NOTNULL的列不能取空值,则插入全部字段的值时,列名表可省略。
例8.23:将一个新学生的信息(学号为S16230102,姓名为李云,性别为女,出生日期为1998-5-7,生源为福建,政治面貌为团员,班级号为C201)
INSERTINTO学生
VALUES(“S16230102“,“李云“,“女“,#1998-5-7#,“福建“,“团员“,“C201“)
2.修改记录数据
格式:UPDATE〈表名〉
SET〈列名〉=〈表达式〉[,〈列名〉=〈表达式〉式,〈E〈)ERE〈条件表达式〉];
功能:修改指定〈表名〉中满足〈条件表达式〉的记录数据。 其中,SET子句中的〈表达式〉的值用于更新相应〈列名〉的字段值。 如果省略WHERE子句,则表示修改表中的所有记录数据。
例8.24:将“学生”表中“张琛”同学的政治面貌改为“党员”。
UPDATE学生
SET政治面貌 =“党员“
WHERE姓名=“张琛“;
3.删除记录数据
格式:DELETE
FROM〈表名〉
[WHERE〈条件表达式〉];
功能:删除指定〈表名〉中满足〈条件表达式〉的所有记录数据。 如果省略WHERE子句,则删除表中的所有记录,使指定表成为空表,但表的定义仍然存在。
例8.25:删除“成绩”表中成绩不及格的学生的记录。
DELETE
FROM成绩
WHERE成绩〈60;