第4章 数据库的查询和视图
4.1.1 选择列
通过SELECT语句的项组成结果表的列。
::=
SELECT [ ALL |DISTINCT ] [ TOP n [ PERCENT ] [ WITH TIES ] ]
{ * /*选择当前表或视图的所有列*/
| { table_name |view_name | table_alias } .* /*选择指定的表或视图的所有列*/
| { colume_name |expression | IDENTITYCOL | ROWGUIDCOL }
[ [ AS ]column_alias ] /*选择指定的列*/
| column_alias =expression /*选择指定列并更改列标题*/
} [ , … n ]
1. 选择一个表中指定的列
一般情况下,希望包含在结果表中的列表清单在SELECT关键字之后,就像前面用到的那样,当在SELECT关键字后面指定*时,就表示全部列都包含在结果表中。不指定*,可以列出一个表中的某些列,各列名之间要以逗号分隔。
4.1.1 选择列
【例4.1】查询XSCJ数据库的XS表中各个同学的姓名、专业名和总学分。
USE XSCJ
SELECT 姓名,专业名,总学分
FROM XS
4.1.1 选择列
【例4.2】查询XS表中计算机专业同学的学号、姓名和总学分。查询XS表中的所有列。
SELECT 学号,姓名,总学分
FROM XS
WHERE 专业名= ‘计算机’
GO
SELECT *
FROM XS
GO
当在SELECT语句指定列的位置上使用*号时,表示选择表的所有列。
执行后将列出XS表中的所有数据,如图4.2所示:
4.1.1 选择列
2. 修改查询结果中的列标题
当希望查询结果中的某些列或所有列显示时使用自己选择的列标题时,可以在列名之后使用AS子句来更改查询结果的列标题名。其中column_alias是指定的列标题。
【例4.3】查询XS表中计算机系同学的学号、姓名和总学分,结果中各列的标题 分别指定为number、name和mark。
SELECT 学号 AS number, 姓名 AS name,总学分 AS mark
FROM XS
WHERE 专业名= ‘计算机’
该语句的执行结果如图4.3所示。
更改查询结果中的列标题也可以使用column_alias=expression的形式。例如:
SELECT number = 学号, name = 姓名, mark = 总学分
FROM XS
WHERE 专业名= ’计算机’
该语句的执行结果与上例的结果完全相同。
4.1.1 选择列
注意,当自定义的列标题中含有空格时,必须使用引号将标题括起来。例如:
SELECT ‘Student number’ = 学号,姓名 AS ‘Student name’, mark = 总学分
FROM XS
WHERE 专业名= ‘计算机’
4.1.1 选择列
3. 替换查询结果中的数据
在对表进行查询时,有时对所查询的某些列希望得到的是一种概念而不是具体的数据。例如查询XS表的总学分,所希望知道的是学习的总体情况,这时,就可以用等级来替换总学分的具体数字。
要替换查询结果中的数据,则要使用查询中的CASE表达式,格式为:
CASE
WHEN 条件1 THEN 表达式1
WHEN 条件2 THEN 表达式2
……
ELSE 表达式
END
SQL Server按照顺序计算每一个条件,如果找到条件为真的语句,SQL Server就执行TEHN关键字后的表达式;否则执行可选的ELSE关键字后的语句。若没有为真的条件,也没有关键字,则CASE表达式返回值为空。
4.1.1 选择列
【例4.4】查询XS表中计算机系各同学的学号、姓名和总学分,对其总学分按以下规则进行替换:若总学分为空值,替换为“尚未选课”;若总学分小于50,替换为“不及格”;若总学分在50与52之间,替换为“合格”;若总学分大于52,替换为“优秀”。列标题更改为“等级”。
SELECT 学号, 姓名,
等级=
CASE
WHEN 总学分 IS NULL THEN ‘尚未选课’
WHEN 总学分 < 50 THEN ‘不及格’
WHEN 总学分 >=50 and 总学分<=52THEN ‘合格’
ELSE ‘优秀’
END
FROM XS
WHERE 专业名=’计算机’
4.1.1 选择列
4. 计算列值
使用SELECT对列进行查询时,在结果中可以输出对列值计算后的值,即SELECT子句可使用表达式作为结果,格式为:
SELECT expression[ , expression ]
【例4.5】按120分计算成绩显示。
SELECT 学号, 课程号,
成绩120=成绩*1.20
FROM XS_KC
4.1.1 选择列
计算列值使用算术运算符:+(加)、-(减)、*(乘)、/(除)和%(取余),其中5种算术运算符(+、-、*、/)可以用于任何数字类型的列,包括:int、smallint、tinyint、decimal、numeric、float、real、money和smallmoney;%可以用于上述除money和smallmoney以外的数字类型。
5. 消除结果集中的重复行
对表只选择其某些列时,可能会出现重复行。例如,若对XSCJ数据库的XS表只选择专业名和总学分,则出现多行重复的情况。可以使用DISTINCT关键字消除结果集中的重复行,其格式是:
SELECT DISTINCTcolumn_name [ , column_name…]
关键字DISTINCT的含义是对结果集中的重复行只选择一个,保证行的唯一性。
【例4.6】对XSCJ数据库的XS表只选择专业名和总学分,消除结果集中的重复行。
SELECT DISTINCT 专业名, 总学分
FROM XS
图4.6消除重复行
与DISTINCT相反,当使用关键字ALL时,将保留结果集的所有行。当SELECT语句中缺省ALL与DISTINCT时,默认值为ALL。
6. 限制结果集返回行数
如果SELECT语句返回的结果集的行数非常多,可以使用TOP选项限制其返回的行数。TOP选项的基本格式为:
TOP n [ PERCENT ]
其中n是一个正整数,表示返回查询结果集的前n行。若带PERCENT关键字,则表示返回结果集的前n%行。
4.1.1 选择列
【例4.7】对XSCJ数据库的XS表选择姓名、专业名和总学分,只返回结果集的前6行。
SELECT TOP 6 姓名,专业名,总学分
FROM XS
4.1.2 选择行
在SQL Server中,选择行是通过在SELECT语句中WHERE子句指定选择的条件来实现的。这一节将详细讨论WHERE子句中查询条件的构成。WHERE子句必须紧跟FROM子句之后,其基本格式为:
在SQL中,返回逻辑值(TRUE或FALSE)的运算符或关键字都可称为谓词。
1. 表达式比较
比较运算符用于比较两个表达式值,共有9个,分别是: =(等于)、(大于)、>=(大于等于)、<>(不等于)、!=(不等于)、!(不大于)。比较运算的格式为:
expression { = |< | <= | > | >= | <> | != | !< | !> } expression
其中expression是除text、ntext和image外类型的表达式。
当两个表达式值均不为空值(NULL)时,比较运算返回逻辑值TRUE(真)或FALSE(假);而当两个表达式值中有一个为空值或都为空值时,比较运算将返回UNKNOWN。
【例4.8】查询XSCJ数据库XS表中通信工程专业总学分大于等于42的同学的情况。
SELECT *
FROM XS
WHERE专业名 = ‘通信工程’ and 总学分 >=42
4.1.2 选择行
2. 模式匹配
LIKE谓词用于指出一个字符串是否与指定的字符串相匹配,其运算对象可以是char、varchar、text、ntext、datetime和smalldatetime类型的数据,返回逻辑值TRUE或FALSE。LIKE谓词表达式的格式为:
string_expression[ NOT ] LIKE string_expression [ ESCAPE ‘escape_character’ ]
【例4.9】查询XSCJ数据库XS表中计算机系的学生情况。查询XSCJ数据库XS表中姓“王”且单名的学生情况。
SELECT *
FROM XS
WHERE 专业名 LIKE ‘计算机’
GO
SELECT *
FROM XS
WHERE 姓名 LIKE ‘王_’
GO
4.1.2 选择行
使用LIKE进行模式匹配时,常使用通配符,即可进行模糊查询。有关通配符的格式和含义请见附录中介绍T-SQL语言的相关说明。
执行结果如图4.8所示。
若要匹配的内容为通配符的字符(包括%、_、[] 、^),可使用关键字ESCAPE。以告诉系统其后的每个字符均作为实际匹配的字符,而不再作为通配符。
3. 范围比较
用于范围比较的关键字有两个:BETWEEN和IN。
当要查询的条件是某个值的范围时,可以使用BETWEEN关键字。BETWEEN关键字指出查询范围,格式为:
expression [ NOT ]BETWEEN expression1 AND expression2
4.1.2 选择行
当不使用NOT时,若表达式expression的值在表达式expression1与expression2之间(包括这两个值),则返回TRUE,否则返回FALSE;使用NOT时,返回值刚好相反。
注意:expression1的值不能大于expression2的值。
使用IN关键字可以指定一个值表,值表中列出所有可能的值,当与值表中的任一个匹配时,即返回TRUE,否则返回FALSE。使用IN关键字指定值表的格式为:
expression IN (expression [,…n])
【例4.10】查询XSCJ数据库XS表中不在1989年出生的学生情况。查询XSCJ数据库XS表中专业名为“计算机”或“通信工程”或“无线电”的学生的情况。
SELECT *
FROM XS
WHERE 出生时间 NOT BETWEEN ‘1989-1-1’ and ‘1989-12-31’
GO
SELECT *
FROM XS
WHERE 专业名 IN (’计算机’, ’通信工程’, ’无线电’)
GO
4.1.2 选择行
该语句与下列语句等价:
SELECT *
FROM XS
WHERE 专业名 = ’计算机’ or 专业名 = ’通信工程’ or 专业名 = ’无线电’
说明:IN关键字最主要的作用是表达子查询。
4. 空值比较
如果两个值当中有一个或者都为空,则对这两个值的比较结果是未知的。NULL谓词提供了一种方法,用来测试值为空或者非空。格式为:
expression IS [NOT ] NULL
当不使用NOT时,若表达式expression的值为空值,返回TRUE,否则返回FALSE;当使用NOT时,结果刚好相反。
【例4.11】查询XSCJ数据库中总学分尚不定的学生情况。
SELECT *
FROM XS
WHERE 总学分 IS NULL
4.1.2 选择行
5. CONTAINS谓词
若需要在表中搜索指定的单词、短语或近义词等,可以使用CONTAINS谓词。CONTAINS谓词用于在表中搜索指定的字符串,可以是精确匹配,也可以是模糊匹配,还可以是加权匹配。要使用CONTAINS谓词,必须在操作的表上事先建立全文索引。
CONTAINS ( {column | * } , ‘’)
上式中,column表示在指定的列中搜索,*表示在所有列中搜索; 为搜索的限定或说明。
::=
{ | | | | }
| {( ) { AND | AND NOT | OR } […n] }
说明:
simple_term:用于说明搜索的是单词还是短语,格式为:word | “phrase”,word为单词,即不含空格和标点符号的字符串;短语是含一个或多个空格的字符串。如果搜索的是短语,则需要用双引号将其括起来。
4.1.2 选择行
prefix_term:给出了要搜索的单词或短语必须匹配的前缀,格式为:
{ “word*” |“phase*”}
其中word为单词,phase为短语,当查询的串是是短语时,需用双引号定界。
generation_term:说明搜索包含原词的派生词,所谓派生词是指原词的名词单、复数形式或动词的各种时态等。格式为:
FORMSOF (INFLECTIONAL , [,…n])
proximity_term:表示搜索包含NEAR或~运算符左右两边的词或短语,格式为: { | } { { NEAR | ~ } { | }[…n]
weight_term:指明本语句是加权搜索,即查询的数据与给定的权重进行加权匹配,格式为:
ISABOUT ( { { | | | } [ WEUGHT (weight_value) ] } [,…n] )
其中weight_value是一个0~1之间的数,表示权重。
6. FREETEXT谓词
与CONTAINS谓词类似,FREETEXT谓词也用于在一个表中搜索单词或短语,并要求表已建全文索引。格式为:
FREETEXT ( {column | * }, ‘freetext_string’ )
其中freetext_string是要搜索的字符串。
FREETEXT的查询精度没有CONTAINS高,他并不要求对它们进行严格的模式匹配。 FREETEXT对所查询的串也没有写法要求,因此FREETEXT也称为自由式查询。
4.1.2 选择行
7. 子查询
子查询通常与IN、EXIST谓词及比较运算符结合使用。
(1)IN子查询
IN子查询用于进行一个给定值是否在子查询结果集中的判断,格式为:
expression [ NOT ]IN ( subquery )
其中subquery是子查询。当表达式expression与子查询subquery的结果表中的某个值相等时,IN谓词返回TRUE,否则返回FALSE;若使用了NOT,则返回的值刚好相反。
【例4.12】在XSCJ数据库中有描述课程情况的表KC和描述学生成绩表的表XS_KC,表的结构和样本数据见附录A。要查找选修了课程号为101的课程的学生的情况:
SELECT *
FROM XS
WHERE 学号 IN
( SELECT 学号 FROM XS_KC WHERE 课程号 = ‘101’ )
4.1.2 选择行
在执行包含子查询的SELECT语句时,系统先执行子查询,产生一个结果表,再执行查询。本例中,先执行子查询:
SELECT 学号
FROM XS_KC
WHERE 课程名 = ‘101’
SELECT *
FROM XS
WHERE 学号 NOT IN
( SELECT 学号
FROM XS_KC
WHERE 课程号 IN
( SELECT 课程号
FROM KC
WHERE 课程名 = '离散数学'
)
)
4.1.2 选择行
(2)比较子查询
这种子查询可以认为是IN子查询的扩展,它使表达式的值与子查询的结果进行比较运算,格式为:
expression { | >= | != | <> | !< | !> } { ALL | SOME | ANY} ( subquery )
其中expression为要进行比较的表达式,subquery是子查询。ALL、SOME和ANY说明对比较运算的限制。
ALL指定表达式要与子查询结果集中的每个值都进行比较,当表达式与每个值都满足比较的关系时,才返回TRUE,否则返回FALSE;
SOME或ANY表示表达式只要与子查询结果集中的某个值满足比较的关系时,就返回 TRUE,否则返回FALSE。
【例4.14】查找比所有计算机系的学生年龄都大的学生。
SELECT *