第5章 数据查询功能 创建和使用查询 在关系数据库中,查询(Query)的作用是从(多个)表中提取面向业务分析的数据,并对业务数据进行汇总性的分析。 查询实现的是DBMS的数据查询功能,而查询的基本工作原理又是关系运算。
5.1 关系运算 在关系数据库中,数据分别存储在不同的二维表中,因此二维表具有一定的独立性。同时,数据库又是具有逻辑关系的数据集合,不同二维表中的数据又是相互联系的。 为了从二维表中提取数据、生成面向业务分析的信息,可以借助于关系运算。 关系运算又可分为两类。一类是传统的关系运算,包括并、差、交、笛卡儿积;另一类是专门的关系运算,包括选择、投影和连接。
5.1.1 传统的关系运算 并(Union)运算:设R和S是n元关系,且两者对应属性的数据类型相同。定义R和S的并运算为 R ⋃ S = { t | t ∈ R ⋁ t ∈ S } ⋁ 代表或者的含义 即:或属于关系R、或属于关系S的记录的集合。 差(Difference)运算:设R和S是n元关系,且两者对应属性的数据类型相同。定义R和S的差运算为 R − S = { t | t ∈ R ⋀ t ∉ S } ⋀ 代表并且的含义 即:属于关系R、但不属于关系S的记录的集合。 交(Intersection)运算:设R和S是n元关系,且两者对应属性的数据类型相同。定义R和S的交运算为 R ⋂ S = { t | t ∈ R ⋀ t ∈ S } = R − ( R − S ) 即:既属于关系R、又属于关系S的记录的集合。 并、差、交运算的前提:关系R和关系S有相同的属性结构。
5.1.1 传统的关系运算
5.1.1 传统的关系运算 笛卡尔积(Cartesian Product)运算:设R是一个n元关系,S是一个m元关系,定义R和S的笛卡尔积运算为 R☓S={(r1,r2,┈,rn,s1,s2,┈,sm)|(r1,r2,┈,rn)∈R ⋀ (s1,s2,┈,sm)∈S}
5.1.2 专门的关系运算 选择(Selection):设R是一个n元关系,F是一个形如riθc的公式,其中θ ∈ {=,≠,>,<,≤,≥},riθc表示属性值ri和指定值c的比较关系(实际上隐含着一个条件,称θ为关系运算符)。定义R的选择运算为 σF(R) = { (r1,r2,┈,ri,┈,rn) | (r1,r2,┈,ri,┈,rn) ∈ R ⋀ riθc } 即:在关系R中选择某一属性值满足一定条件(与指定值的比较关系成立)的记录。
5.1.2 专门的关系运算 例1,在如下表Student中,若要找出所有女学生的元组,就可以使用选择运算来实现,其中的条件riθc是:Sex=“女”。 StudentID Name Sex Birthday Entrancescore 981101 赵文化 男 2-28-80 500 981102 徐逸华 6-7-81 630 981103 郭茜茜 女 11-17-82 650 981201 钱 途 5-1-80 380 981202 高 涵 11-06-80 981203 李晓鸣 400 σ Sex=“女”(Student) = { t | t ∈ Student ⋀ t.Sex=“女”} 选择运算是对单个关系进行水平分解,是从行的角度进行的运算。
5.1.2 专门的关系运算 例2,在如下表Student中,若要找出所有性别为女且入学成绩在500分以上(包括500分)的学生记录,也可以使用选择运算来实现,其中的条件是:(Sex=“女”)⋀(Entrancescore≥500)。 StudentID Name Sex Birthday Entrancescore 981101 赵文化 男 2-28-80 500 981102 徐逸华 6-7-81 630 981103 郭茜茜 女 11-17-82 650 981201 钱 途 5-1-80 380 981202 高 涵 11-06-80 981203 李晓鸣 400 σ(Sex=“女”)⋀(Entrancescore ≥ 500)(Student) = { t | t ∈ Student ⋀ t.Sex=“女” ⋀ t.Entrancescore ≥ 500 } 选择运算中的条件可以是多个简单条件的逻辑组合。
5.1.2 专门的关系运算 投影(Projection):设R是一个n元关系,定义R的投影运算为 Πi1,i2,┈,im(R) = { (ri1,ri2,┈,rim) | (r1,r2,┈,ri1,ri2,┈,rim,┈,rn) ∈ R } 其中i1,i2,┈,im表示所选取属性列的编号,且m < n。 即:从关系R中选取若干属性列组成新的关系。
5.1.2 专门的关系运算 例如,在如下表Student中,若要仅显示所有学生的StudentID(学号)、Name(姓名)和Sex(性别),那么可以使用投影运算来实现。 StudentID Name Sex Birthday Entrancescore 981101 赵文化 男 2-28-80 500 981102 徐逸华 6-7-81 630 981103 郭茜茜 女 11-17-82 650 981201 钱 途 5-1-80 380 981202 高 涵 11-06-80 981203 李晓鸣 400 ΠStudentID, Name, Sex (Student) 投影运算是对单个关系进行垂直分解,是从列的角度进行的运算。
5.1.2 专门的关系运算 连接(Join)运算:设R是n元关系,S是m元关系,A是R的属性,B是S的属性,A和B的值域具有相同的数据类型,θ ∈ {=,≠,>,<,≤,≥}。定义R和S的连接(Jion)运算为 R⋈AθB S = { rs | r∈R ⋀ s∈S ⋀ (r[A] θ s[B]) } 其中,r[A]表示元组r在属性A上的值,s[B]表示元组s在属性B上的值。r=(r1,r2, ┈r[A], ┈, rn),s=(s1,s2,┈, s[B]┈, sm),rs形如(r1,r2, ┈r[A], ┈, rn, s1,s2,┈, s[B]┈, sm)。 并称A和B是连接属性。
5.1.2 专门的关系运算 需要注意的是,连接属性可以有不同的名称,但必须表示相同的含义并有相同的数据类型,以保证属性值的可比性。
5.1.2 专门的关系运算 需要特别注意的是,等值连接与一对多表间关系有着密切的联系:一对多表间关系为等值连接运算提供了基础,通过一对多表间关系中的关联字段可以进行等值连接运算。实际上,等值连接运算中的连接属性就是一对多表间关系中的关联字段。 StudentID是关系Student的主键,StudentNO是关系CourseGrade相对于关系Student的外键(关系CourseGrade的主键是StudentID和Course的组合);关系Student和关系CourseGrade是父表和子表的一对多表间关系,关联字段在关系Student和关系CourseGrade中分别是StudentID和StudentNO,同时也是等值连接运算中的连接属性。
5.1.2 专门的关系运算 由此可见,在一对多表间关系的基础上,将关联字段作为连接属性可以进行等值连接运算,从而将父表与子表中的数据有机地联系在一起。 在上述等值连接运算的结果关系中,学生姓名(Name)与课程成绩(Grade)的匹配正是通过等值连接运算得到的。
5.1.2 专门的关系运算 等值连接和笛卡儿积的比较
5.1.2 专门的关系运算 若在等值连接的结果关系中去掉重复的属性,或者说,连接属性在结果关系中只出现一次,则此连接称为自然连接。
5.1.2 专门的关系运算 通过4.3.3和4.3.4两节的介绍,我们已经知道:在关系数据库中,为了减少数据冗余,业务数据是分散地存储在多个二维表中的,每个二维表具有相对的独立性。 但二维表之间又存在着相互联系,二维表之间的联系主要是指父表与子表之间的一对多联系——通过关联字段将父表与子表中的数据联系起来。 连接运算就具体实现了相关表中的数据联系。
5.1.3 关系运算的总结 关系运算是对关系进行的闭合运算,因此,运算对象是关系,并且运算的结果仍为关系。 并、差、交、笛卡儿积为二元关系运算,即是对两个关系进行的运算,并且并、差、交运算要求两个关系的对应属性有相同的含义和数据类型。 选择、投影为一元关系运算,即对单个关系进行的运算;选择运算是从行的角度进行的运算,投影运算是从列的角度进行的运算。 连接为二元关系运算,其中的两个关系是通过连接属性完成运算的,且连接属性必须有相同的数据类型并表示相同的含义。在关系数据库中,等值连接运算是最常见的连接运算。 在RDBMS中,数据查询功能就是通过选择、投影和等值连接运算完成的。换句话说,从数据库中的若干表提取所需要的数据,都要借助于选择、投影和等值连接运算才能实现。在Access数据库中,“查询”对象中主要体现和包含了关系的选择、投影和等值连接运算。
5.2 查询的设计与创建 在Access数据库中,查询(Query)可以从多个表中提取数据、并对数据进行组合和分析。 使用查询,可以按照不同的准则或方式对表中的数据进行抽取,以得到用户需要的数据和信息。
5.2.1 查询、关系运算及SELECT命令 在Access数据库中,大部分查询可以使用数据查询语言(Data Query Language,DQL)中的SELECT命令来实现数据查询功能。 SELECT命令的基本语法格式为 SELECT 字段名1[,字段名2…] FROM 表名 [WHERE 条件表达式] [GROUP BY 字段列表] [ODRDE BY 字段名 ASC|DESC] 关系的选择、投影和等值连接运算都可以通过SELECT命令来体现和实现。
5.2.1 查询、关系运算及SELECT命令 选择运算 σ Sex=“女”(Student) = { t | t ∈ Student ⋀ t.Sex=“女”} 可以使用如下SELECT命令来实现 SELECT StudentID, Name, Sex, Birthday, Score FROM Student WHERE Sex=“女” 投影运算 ΠStudentID, Name, Sex (Student) 可以使用如下SELECT命令来实现 SELECT StudentID, Name, Sex FROM Student 多数情况下,一个查询对象对应着一个SELECT命令
5.2.2 查询的视图 在Access数据库中,查询对象有五种视图。这五种视图及其作用分别如下: 1.设计视图:用于创建新的查询对象,或者修改已有的查询对象; 2.数据表视图:可以以二维表的形式显示查询结果; 3.SQL视图:用于查看查询对象所对应的SELECT命令,该命令属于SQL语句; 4.数据透视表视图:以表格形式对查询结果进行进一步的多维分析; 5.数据透视图视图:以图形方式显示、对比查询结果。
5.2.2 查询的视图 查询的设计视图 查询的含义是:从“供应商”和“产品”表中查询单价在10与20之间(包括10和20)的产品信息,并检索出其中的公司名称、产品名称、单价等三个字段上的数据,而且将查询结果按照“公司名称”的降序排列。
5.2.3 在设计视图中创建查询 在Access数据库中,创建查询有两种方法。 1.在设计视图中创建查询。 2.使用向导创建查询。 其中,“在设计视图中创建查询”的方法最为灵活、有效和实用,本章将详细介绍。 【练习5-1(P92)】查询单价在10~20元(包括10元和20元)的产品数据,要求在查询结果中列出每个产品的供应商的公司名称以及相应的产品名称,并将查询结果按照公司名称的降序排列。
5.2.3 在设计视图中创建查询 “罗斯文”示例数据库中的表间关系及对应的关联字段 父表 子表 关联字段 表间关系类型 供应商 产品 供应商ID 一对多 类别 类别ID 客户 订单 客户ID 雇员 雇员ID 运货商 运货商ID 订单明细 订单ID 产品ID
5.2.3 在设计视图中创建查询 SELECT 供应商.公司名称, 产品.产品名称, 产品.单价 ③ FROM 供应商 INNER JOIN 产品 ON 供应商.供应商ID = 产品.供应商ID ① WHERE (((产品.单价)>=10 And (产品.单价)<=20)) ② ORDER BY 供应商.公司名称 DESC; ④
5.2.3 在设计视图中创建查询
5.2.4 在查询中使用条件来检索特定记录 条件是查询中用来识别所需特定记录的限制准则。使用查询条件,可以从数据来源中检索出具有指定特征的记录。 在查询的设计视图中指定条件,就是在设计网格中某字段对应的“条件”单元格中输入相应的表达式,表达式描述了所查询的记录在该字段上的取值具有什么样的特征。 查询条件中的表达式可以是常量、变量、运算符、字段名和函数等元素按照一定规则的组合,代表着一定的准则。
5.2.4 在查询中使用条件来检索特定记录 在设计视图中创建查询条件的常见办法有: 1.检索字段值为指定常量。例如,如果只查询“产品名称”为“鸭肉”的产品记录,只需要在“产品名称”字段下方对应的“条件”单元格中输入“鸭肉”即可。 2.检索字段值介于指定值之间的记录,即通过使用 Between...And 运算符或比较运算符(=、<、>、<>、<= 和 >=)来创建条件,具体例子如表5-2-2所示。 表 5-2-2 字段值介于指定值之间的查询条件 表达式 含义 >234 大于234的数 <>10 不等于10的数 Between 1 And 10 1到10的数值(包括1和10) Between #1996-1-1# And #1996-12-31# 日期由1996-1-1到1996-12-31
5.2.4 在查询中使用条件来检索特定记录 3.使用通配符和Like运算符检索部分或完全匹配的内容。所谓通配符(Wildcard Character),就是可用于替代一个或多个字符的特殊键盘字符。常见的通配符如下表所示。 字符 用法 示例 * 代表任意数目的任意字符,包括空格 wh* 可以找到what、white和why ? 代表任何单个字符 b?ll 可以找到ball、bell和bill # 代表任何单个数字字符 1#3 可以找到103、113、123 [ ] 与方括号内任何单个字符匹配 b[ae]ll可以找到ball和bell但找不到bill ! 匹配任何不在方括号之内的字符 b[!ae]ll可以找到bill和bull但找不到ball或bell _ 与范围内的任何一个字符匹配。必须按照ASCII码以递增次序来指定区域 b[a-c]d 可以找到bad、bbd和bcd 例如,为了查找“产品名称”字段包括“X…X鱼”的产品记录,则可以在该字段对应的“条件”单元格中输入Like “*鱼”,这样就可能找出“产品名称”为“雪鱼”、“黄鱼”、“金枪鱼”的产品记录;而如果在“条件”单元格中输入Like “?鱼”,则只可能找出“产品名称”为“雪鱼”、“黄鱼”的产品记录,而找不出“产品名称”为“金枪鱼”的产品记录。
5.2.4 在查询中使用条件来检索特定记录 4.检索指定值范围以外的记录。例如,可以在“客户ID”字段对应的“条件”单元格中输入 Not Like “A*”,以查找“客户ID”不是以字母A开头的客户记录。又例如,在“单价”字段对应的“条件”单元格输入 Not 10(此条件等价于 <>10 ),以查找“单价”不为10的产品记录。 5.用In运算符检索包括值列表中一个值的记录。例如,在“供应商”表中查找北京、上海或沈阳等城市的供应商记录,可以在“城市”字段对应的“条件”单元格中输入下列表达式:In ("北京","上海","沈阳")。
5.2.4 在查询中使用条件来检索特定记录 6.构造复合的条件。 当需要检索必须同时满足多个条件的数据时,可以使用And逻辑运算符将这些条件连接起来。例如,为了表示“单价在10元和20元之间(包括10元和20元)”的条件,既可以在“单价”字段对应的“条件”单元格中输入表达式“Between 10 And 20”,也可以输入表达式“>=10 And <=20”。 当需要检索只需符合多个条件之一的数据时,则可以使用Or逻辑运算符将这些条件连接起来。例如,在“产品名称”字段对应的“条件”单元格中输入表达式:"鸭肉" Or "鸡肉",则表示检索“产品名称”为“鸭肉”或“鸡肉”的产品记录。
5.2.4 在查询中使用条件来检索特定记录 6.构造复合的条件。 在相同字段或不同字段对应的“条件”或“或”单元格中输入表达式,也可以构造出复合的条件。
5.2.4 在查询中使用条件来检索特定记录 6.构造复合的条件。 ((产品ID Between 1 And 10) AND (单价>30)) Or ((产品ID Between 20 And 30) AND (单价<10))
5.3 选择查询 在Access数据库中,根据对数据来源的操作方式以及对查询结果组织形式的不同,可以将查询分为选择查询、交叉表查询、操作查询、参数查询和SQL查询五大类。本节首先介绍选择查询。 在Access数据库中,选择查询是最常见的查询类型,它从一个或多个表中检索数据,并且以二维表的形式显示查询结果。 【练习5-1】中所创建的查询就是一个选择查询,该查询从“供应商”和“产品”表中检索有关供应商的公司名称、产品名称和单价等产品数据,并且这些数据都直接来自于相关表中的对应字段。 此外,在Access查询中,还可以利用Access内置函数从字段数据中进一步提取信息。
5.3.1 利用Access内置函数从字段数据中提取信息 【练习5-2(P99)】 “雇员”表 雇员ID 身份证号码 姓氏 名字 头衔 尊称 出生日期 雇用日期 上级 1 100201196812081122 张 颖 销售代表 女士 1968-12-8 1992-5-1 2 201234196202192189 王 伟 副总裁(销售) 博士 1962-2-19 1992-8-14 3 51012719730830892X 李 芳 1973-8-30 1992-4-1 4 340123196809191223 郑 建杰 先生 1968-9-19 1993-5-3 5 623452196503042312 赵 军 销售经理 1965-3-4 1993-10-17 根据“出生日期”或“身份证号码”推算雇员的“年龄”; 将雇员的“姓氏”和“名字”组合成“姓名”。
5.3.1 利用Access内置函数从字段数据中提取信息
5.3.1 利用Access内置函数从字段数据中提取信息 在一个具体的RDBMS产品中,大都提供了专门的内置函数和运算符,利用这些内置函数和运算符可以对表中的数据进行专门的处理,以便从数据中提取更细的或特定的数据。 例如,通过如下形式的表达式 "第" & DatePart("q",[订购日期]) & "季度“ 可以得到类似于“第1季度”、“第2季度”、“第3季度”和“第4季度”这样的文本串数据。 根据所处理数据的类型不同,可以将Access内置函数划分为算术函数、文本函数、日期/时间函数等。每种函数只能处理特定类型的数据。
5.3.1 利用Access内置函数从字段数据中提取信息 函数类型 函数形式 用法说明 算术函数 Abs(number_exp) 返回数值表达式number_exp值的绝对值。 Int(number_exp) 返回将数值表达式number_exp值向下取整到最接近的整数,即不大于数值表达式值的最大整数。 Sqr(number_exp) 返回数值表达式number_exp值的平方根。 Sgn(number_exp) 返回数值表达式number_exp值的符号值。即当数值表达式的值大于0时,返回值为1;当数值表达式的值等于0时,返回值为0;当数值表达式的值小于0时,返回值为-1。
5.3.1 利用Access内置函数从字段数据中提取信息 文本 函数 Left(text,num_chars) 返回文本串text中的第一个或前几个字符。例如,Left("database",4)的返回值为"data"。 Right(text,num_chars) 返回文本串text中最后一个或多个字符。例如,Right("数据库管理系统",2)的返回值为"系统"。注意:一个汉字相当于一个字符。 Mid(text,num_chars_1,num_chars_2) 返回文本串text中从第num_chars_1开始的连续的num_chars_2个字符。例如,Mid("Database Management System",10,10)的返回值为"Management"。注意:一个空格也算一个字符。 Trim(text) 除了中间的空格外,清除文本串两端的所有空格。例如,Trim(" RDBMS is useful! ")的返回值为"RDBMS is useful!"。
5.3.1 利用Access内置函数从字段数据中提取信息 日期/ 时间 函数 Day(date) 返回日期型数据date的号数,表示给定日期date是一个月当中的哪一天。 Month(date) 返回日期型数据date的月数,表示给定日期date是一年当中的哪个月。 Year(date) 返回日期型数据date的年数,表示给定日期date是哪一年。 DatePart(interval,date) 返回日期型数据date的对应数值。参数interval是要返回的日期部分的缩写,有效的缩写示例为:"yyyy"表示四位数字格式的年份,"q"表示季度,"m"表示月份。 例如,DatePart("yyyy",#2008-8-8#)返回2008(相当于Year(#2008-8-8#)),DatePart("q",#2008-8-8#)返回3,DatePart("m",#2008-8-8#)返回8(相当于Month(#2008-8-8#))。
5.3.2 基于记录分组的选择查询 在对数据库中的数据进行分析时,有时需要依据一定的标准将有关数据(记录)进行分组,并在此基础上对记录作总计、计数、平均值以及其他类型的聚合计算。 又例如,计算并对比每个季度的销售额,就可以根据交易时间将同一季度的交易记录归入同一组并计算每笔交易的销售额,然后将同一季度中每笔交易的销售额加起来,就可以得到该季度的销售额。 Access数据库中的选择查询就可以实现这种基于记录分组的聚合计算。
5.3.2 基于记录分组的选择查询 【练习5-3(P103)】创建选择查询,统计每个供应商提供的产品种类数,并显示供应商的公司名称和对应的产品种类数。 “产品”表 产品ID 产品名称 供应商ID 类别ID 单位数量 单价 库存量 订购量 再订购量 1 苹果汁 每箱24瓶 ¥18.00 39 10 2 牛奶 ¥19.00 17 40 25 3 蕃茄酱 每箱12瓶 ¥10.00 13 70 4 盐 ¥22.00 53 5 麻油 ¥21.35 6 酱油 ¥25.00 120 7 海鲜粉 每箱30盒 ¥30.00 15 8 胡椒粉 ¥40.00
5.3.2 基于记录分组的选择查询 SELECT 供应商.公司名称, Count(产品.产品ID) AS 产品ID之计数 FROM 供应商 INNER JOIN 产品 ON 供应商.供应商ID = 产品.供应商ID GROUP BY 供应商.公司名称;
5.3.2 基于记录分组的选择查询 基于“分组”的聚合函数和其他选项 选定 若要计算 使用下列字段数据类型 总计 字段值的总和 数字、日期/时间、货币和自动编号 平均值 字段值的平均值 最小值 字段值的最小值 文本、数字、日期/时间、货币和自动编号 最大值 字段值的最大值 计数 字段值的个数 文本、备注、数字、日期/时间、货币、自动编号、是/否和 OLE 对象 分组 定义要执行计算的分组。例如,如果要按类别计算“销售额总计”,就对“类别名称”字段选定“分组”
5.3.2 基于记录分组的选择查询 【练习5-4(P106)】采用记录分组的查询方法,对每张订单的销售额小计(不考虑折扣情况)进行统计查询,要求显示订单ID、客户的公司名称和每张订单的销售额小计。
5.3.2 基于记录分组的选择查询
5.3.2 基于记录分组的选择查询
5.4 交叉表查询 【练习5-5(P109)】根据查询结果设计分组选择查询(由学生自己完成)。下图是一个分组选择查询的数据表视图,其中,“公司名称”和“类别名称”为分组基准字段,第3列为某供应商提供的某大类别的产品种类数。
5.4 交叉表查询 【练习5-6(P109)】创建查询结果(数据表视图)如下图所示的交叉表查询。
5.4.1 创建交叉表查询
5.4.2 多级交叉表查询 【练习5-7(P111)】建立查询结果(数据表视图)如上图所示的交叉表查询,其中的“年度”和“季度”以“订购日期”为标准,计算销售额时不考虑折扣情况。
5.4.2 多级交叉表查询 “罗斯文”示例数据库中的表间关系及对应的关联字段 父表 子表 关联字段 表间关系类型 供应商 产品 供应商ID 一对多 类别 类别ID 客户 订单 客户ID 雇员 雇员ID 运货商 运货商ID 订单明细 订单ID 产品ID
5.4.2 多级交叉表查询
5.5 操作查询 在Access数据库中还可以创建操作查询,操作查询能够在一次操作中对表中的多条记录进行改动或移动。
5.5.1 生成表查询 在生成表查询中,可以利用一个或多个表中的全部或部分数据生成新表。 【练习5-8(P113)】利用“产品”表中的数据,生成如表5-8所示的新表,新表中仅包含产品ID在10与15之间的产品数据。 表 5-8 由生成表查询生成的新表 产品ID 产品名称 10 蟹 11 民众奶酪 12 德国奶酪 13 龙虾 14 沙茶 15 味精
5.5.1 生成表查询 SELECT 产品.产品ID, 产品.产品名称 INTO 生成表查询创建的新表 FROM 产品 在菜单栏中选择【查询】|【生成表查询】命令 SELECT 产品.产品ID, 产品.产品名称 INTO 生成表查询创建的新表 FROM 产品 WHERE (((产品.产品ID) Between 10 And 15));
5.5.2 更新查询 在更新查询中,能够对表中多条记录在若干字段上的值同时进行更改。 【练习5-9(P114)】在“订单”表中,将“订购日期”为1996-7-8的订单的“到货日期”更改为1996-8-4。 【分析】在此更新查询中,“订购日期”是查询条件的基准字段,需要对哪些记录进行相应的更改是根据“订购日期”的值判断的;如果某订单的“订购日期”为1996-7-8,则需要将其对应的“到货日期”更改为1996-8-4。
5.5.2 更新查询 在菜单栏中选择【查询】|【更新查询】命令 UPDATE 订单 SET 订单.到货日期 = #8/4/1996# WHERE (((订单.订购日期)=#7/8/1996#)); 从严格意义上说,该更新查询的SQL语句是数据操作语言当中的一条UPDATE命令。
5.5.3 追加查询 利用追加查询,可以从一个表中提取部分字段上的数据、然后向另一个表追加这些数据,但这两个表中的对应字段应该有相同的数据类型。 【练习5-10(P116)】创建追加查询,将“新类别”表中的数据追加到“类别”表。 【分析】在“新类别”表和“类别”表中,“类别ID”、“类别名称”和“说明”是共有的字段,并且对应字段的数据类型相同。另一方面,虽然“类别ID”字段在两个表中都是主键,但是主键上的值并不冲突,所以可以将“新类别”表中的数据追加到“类别”表中。
5.5.3 追加查询 INSERT INTO 类别 ( 类别ID, 类别名称, 说明 ) 在菜单栏中选择【查询】|【追加查询】命令 INSERT INTO 类别 ( 类别ID, 类别名称, 说明 ) SELECT 新类别.类别ID, 新类别.类别名称, 新类别.说明 FROM 新类别;
5.5.4 删除查询 当表中有大量记录需要删除时,可以在“数据表视图”中使用手动方式删除这些记录,但这种方法效率较低。而借助“删除查询”删除指定记录则是更为有效的方法。 【练习5-11(P117)】创建删除查询,从“类别”表中删除“类别ID”在9至11之间的3条记录。 【分析】在此删除查询中,“类别ID”是查询条件中的基准字段,需要对哪些记录进行相应的删除操作是根据“类别ID”的值决定的——如果某条记录在“类别ID”字段上的值在9至11之间,则需要将其从“类别”表中删除。
5.5.4 删除查询 在菜单栏中选择【查询】|【删除查询】命令 DELETE 类别.类别ID FROM 类别 WHERE (((类别.类别ID)>=9 And (类别.类别ID)<=11)); 从严格意义上说,该删除查询的SQL语句是数据操作语言当中的一条DELETE命令。
5.6 参数查询 在本节之前介绍的选择查询和交叉表查询中,查询条件是预先定义好的。一旦查询设计好之后,查询结果中所包含的数据就会固定下来,即每次运行查询都会获得相同的数据。 【练习5-12(P118)】(由学生自己完成)创建选择查询,并以订购日期为基准字段,查询1996年度第四季度每个客户的订单情况。要求列出客户的公司名称、订单ID及对应的订购日期,并且将查询结果按公司名称的升序排列。
5.6 参数查询 【练习5-13(P118)】创建参数查询,并以订购日期为基准字段,查询某一时间段内每个客户的订单情况。要求列出客户的公司名称、订单ID及对应的订购日期,并且将查询结果按公司名称的升序排列。 【分析】为了实现该查询的要求,需要使用“客户”和“订单”两个表中的数据。并且这两个表可以通过关联字段“客户ID”连接在一起。此外,某一时间段是在运行查询时临时指定的,为此可以设置“开始日期”与“结束日期”两个参数。
5.6 参数查询 参数查询所对应的SELECT命令 SELECT 客户.公司名称, 订单.订单ID, 订单.订购日期 FROM 客户 INNER JOIN 订单 ON 客户.客户ID = 订单.客户ID WHERE (((订单.订购日期) Between [开始日期] And [终止日期])) ORDER BY 客户.公司名称;
5.7 SQL查询 在Access数据库中,有些特殊的查询无法在设计视图中创建,只能通过在SQL视图中直接输入SQL语句来创建。这些只能在SQL视图中直接输入SQL语句来创建的查询,称为SQL查询。 在Access数据库中,SQL查询可分为以下四类:联合查询、子查询、数据定义查询和传递查询。本小节只介绍前三种SQL查询。
5.7.1 联合查询 SELECT 供应商.公司名称, 供应商.城市 FROM 供应商; 在一个新建查询的SQL视图中直接输入 SELECT 供应商.公司名称, 供应商.城市 FROM 供应商 UNION SELECT 客户.公司名称, 客户.城市 FROM 客户 ORDER BY 城市;
5.7.2 子查询 在Access数据库中,可以将一个查询的结果作为另一个查询的输入。其中,前一个查询称为子查询,后一个查询称为主查询。或者说,子查询包含在主查询中。 可以使用设计视图创建主查询,再在主查询的设计视图中输入子查询对应的SELECT命令。 通常情况下,子查询出现在主查询的条件当中。 【练习5-14(P121)】从“产品”表中,查询单价在平均值之上的产品信息,要求列出“产品ID”、“产品名称”和“单价”等产品信息。
5.7.2 子查询 利用子查询求出单价的平均值 SELECT Avg(产品.单价) AS 单价之平均值 FROM 产品
5.7.2 子查询 在主查询的条件中使用子查询 SELECT 产品.产品ID, 产品.产品名称, 产品.单价 FROM 产品 WHERE (产品.单价>(SELECT Avg(产品.单价) AS 单价之平均值 FROM 产品)); 需要特别注意的是,单价的平均值是一个“单独的值”。这种情况下,子查询必须包含“一行一列”的查询结果,或者说,子查询的结果必须是一个值。
5.7.2 子查询 【练习5-15(P122)】创建主查询/子查询,找出“华北”地区供应商提供的所有产品,并列出“产品ID”、“供应商ID”和“产品名称”。 【分析】首先,需要从“供应商”表中找出“华北”地区的供应商的“供应商ID”列表,为此可以在设计视图中创建一个子查询,进而得到子查询对应的SELECT命令;然后,再从“产品”表中找出“供应商ID”在子查询结果(即“供应商ID”列表)中的产品记录,即可同时找出这些产品的“产品ID”、“供应商ID”和“产品名称”。
创建子查询,从“供应商”表中找出所有“华北”地区的供应商 5.7.2 子查询 创建子查询,从“供应商”表中找出所有“华北”地区的供应商 SELECT 供应商.供应商ID FROM 供应商 WHERE 供应商.地区="华北" 子查询的查询结果是“多行一列”的“供应商ID”列表
5.7.2 子查询 创建主查询,从“产品”表中找出“华北”地区供应商提供的所有产品 SELECT 产品.产品ID, 产品.供应商ID, 产品.产品名称 FROM 产品 WHERE 产品.供应商ID In (SELECT 供应商.供应商ID FROM 供应商 WHERE 供应商.地区="华北")
5.7.3 数据定义查询 使用数据定义查询,能够创建、删除、更改表,或创建表的索引。 从本质上说,Access数据库中的数据定义查询就是数据定义语言(Data Definition Language,DDL)当中的数据定义语句。 每个数据定义查询只能由一个数据定义语句完成。 在数据定义查询中,可以使用以下数据定义语句: CREATE TABLE,创建表。 ALTER TABLE,在已有表中添加新字段或约束,也可以删除已有字段(及该字段上的数据)。 DROP TABLE,从数据库中删除表。
5.7.3 数据定义查询 【练习5-16(P123)】按照以下要求,使用CREATE TABLE命令创建“产品1”表。 1.关系模式:产品1(产品ID、产品名称、单位数量、单价); 2.其中“产品ID”为主键; 3.字段的数据类型及字段属性如下表所示。 “产品1”表中字段的数据类型及字段属性 字段名称 数据类型 字段大小(字段属性) 产品ID 数字 整型 产品名称 文本 40 单位数量 20 单价 货币 CREATE TABLE 产品1 (产品ID INTEGER, 产品名称 TEXT(40), 单位数量 TEXT(20), 单价 CURRENCY, PRIMARY KEY (产品ID)) 在一个新建查询的SQL视图中输入上述CREATE TABLE命令
5.8 结构化查询语言 在关系型数据库中,结构化查询语言(Structured Query Language,SQL)是用于对存放在计算机数据库中的数据进行组织、管理和检索的工具。尽管查询是设计SQL的最初目的,但SQL决不仅仅是一个查询工具,SQL可用于控制RDBMS提供给用户的所有功能,包括: 数据定义(Data Definition):SQL可用于定义被存放数据的结构和组织,以及数据项之间的关系。 数据查询/检索(Data Query/Retrieval):SQL能使用户或应用程序从数据库中检索数据并使用这些数据。 数据操纵(Data Manipulation):用户或应用程序通过SQL更改数据库,如增加新数据,删除旧数据,修改已存入的数据等。 存取控制(Access Control):SQL可用来限制用户检索、增加和修改数据的权限,保护所存储的数据不被非法存取。 数据共享(Data Sharing):SQL可用于调整数据让并发用户共享,以保证用户之间彼此不受影响。 数据完整性(Data Integrity):SQL能对数据库的完整性条件作出规定,以使数据库中的数据不会因为修改紊乱或系统出错而被破坏。
5.8 结构化查询语言 对前面已经学过的SQL命令的归纳和总结 RDBMS的功能 SQL 的分类 SQL命令 SQL命令的作用 数据定义功能 数据定义语言(Data Definition Language,DDL) CREATE TABLE 创建/定义表 ALTER TABLE 对已有表的结构进行修改 DROP TABLE 删除已有表 数据操纵功能 数据操纵语言(Data Manipulation Language,DML) INSERT INTO 在表中插入记录 UPDATE 对表中指定记录的某字段值进行修改 DELETE 从表中删除指定记录 数据查询功能 数据查询语言(Data Query Language,DQL ) SELECT 从表中提取满足条件的数据
5.8 结构化查询语言 使用SQL对数据库中的数据进行查询的工作原理及过程:①用户将数据查询请求(如SELECT命令)以SQL语句的形式提交给RDBMS;②RDBMS依据SQL语句中的要求,在数据库中的相关表中检索数据;③检索结果再通过RDBMS返回给用户。 由此可见,在用户和数据库之间,RDBMS起着中间桥梁的作用。
5.9 小结 在RDBMS中,数据查询功能是通过关系的选择、投影和等值连接运算完成的。 在Access数据库中,“查询”对象中主要体现和包含了关系的选择、投影和等值连接运算。 在企业的信息系统中,存储了大量的客户个人数据和客户交易数据。从这些基础业务数据中,可以使用Access查询进一步提取更多的信息。
5.9 小结 各类Access查询的特点和作用 查询类型 主要特点和作用 选择查询 能够进一步提取更多的信息【练习5-2】 可以创建基于分组的查询【练习5-3】 只可以进行纵向的归类汇总【练习5-4】【练习5-5】【练习5-12】 交叉表查询 可以创建基于分组的查询【练习5-6】 可以进行纵向或横向的(多级)分组汇总【练习5-7】 操作查询 本质上实现的是RDBMS的数据操纵功能 生成表查询【练习5-8】、更新查询【练习5-9】、追加查询【练习5-10】、删除查询【练习5-11】 参数查询 当需要多次执行同一查询、但每次要检索的数据却不同时,可以使用参数查询。根据用户输入的不同参数,参数查询能够动态地构造不同的查询条件,从而得到包含不同数据的查询结果【练习5-13】 SQL查询 直接使用SQL创建复杂的查询(如联合查询、子查询【练习5-14】【练习5-15】) 数据定义查询本质上实现的是RDBMS的数据定义功能【练习5-16】
5.9 小结 在创建和使用查询时,应该注意以下问题: 1.明确查询的作用。利用查询,主要是为了从多个相关表中提取关于特定业务需求的数据,或者对数据进行基于分组的总计、计数、求平均值、最大值和最小值等聚合分析。 2.选择正确的数据来源。①注意名称相同的字段与表之间的正确对应关系。例如,在“罗斯文”示例数据库中,“供应商”、“客户”和“运货商”三个表中都有“公司名称”字段,在设计查询时很容易搞混淆。②避免使用多余的表。否则,查询结果中的数据会被放大。③避免遗漏起着“桥梁”联接作用的表。例如在【练习5-7】的交叉表查询中,虽然没有直接使用“产品”表中的某个字段,但仍然需要将“产品”表作为查询的数据来源之一,否则“类别”表和“订单明细”表之间就无法建立联系。
5.9 小结 3.在设计视图中建立正确的表间联系。①在建立表间联系时,一定要选择正确的关联字段。而关联字段不需要有相同的名称,但必须有相同的数据类型、并具有相同的字段含义。例如,在“罗斯文”示例数据库中,“运货商”表和“订单”表之间的关联字段,在“运货商”表中是“运货商ID”,在“订单”表中是“运货商”。②在多表查询中,要确保每个数据表至少与另外一个表联系。如果在设计视图中某个表处于孤立状态,则查询结果就会不正确。 4.选择正确的查询类型。根据每种查询类型的特点和作用,选择正确的查询类型。例如,当统计销售额时,可以考虑具有数据分组功能的选择查询或交叉表查询。当需要多次执行同一查询,但每次要检索的数据却不同时,则可以考虑使用参数查询。
5.9 小结 5.灵活地使用Access内置函数创建计算字段。在Access查询中,利用内置函数可以从字段数据中进一步提取信息。为此,需要准确理解常用内置函数的作用和使用方法。例如,在【练习5-2】中,利用文本串连接运算符“&”可以将“姓氏”和“名字”组合成“姓名”,利用内置函数Year()、Date()和Mid()可以根据“身份证号码”和“出生日期”推算“雇员”的“年龄”。利用DatePart()函数可以从日期数据中提取年份、季度和月份等信息。 6.正确创建基于分组的计算字段。首先,确保选择正确的分组基准字段。例如,在“罗斯文”示例数据库中,描述订单不同处理状态的时间有“订购日期”、“发货日期”和“到货日期”三种日期,当需要创建基于日期的分组基准字段时,应选择正确的日期并加以说明。其次,选择正确的聚合函数。基于记录分组可以进行聚合分析,但要特别注意区分计数(Count)和总计(Sum)的不同——计数(Count)返回分组中记录的数目,而总计(Sum)是对记录分组内的相应数值进行累加求和运算。 7.正确创建查询条件。尤其要注意通配符在条件中的灵活运用,以及如何构造复合的条件。关于如何创建查询条件,可以参见第5.2.4节。