页数:140页文件大小:2.57 MB来源: 空间数据库与SQLppt课件
本课件先以选择、投影、连接等关系运算建立查询的直观认识,随后按SELECT语句的各子句逐项展开,覆盖条件查询、模式匹配、聚合函数、分组排序、连接与子查询,最后讲解视图的创建使用与游标的操作流程。
4.1关系运算4.2数据库的查询4.3视图4.4游标
1.选择(Selection)选择是单目运算,其运算对象是一个表。该运算按给定的条件,从表中选出满足条件的行,形成一个新表,作为运算结果。选择运算的记号为F(R)。其中,是选择运算符,下标F是一个条件表达式,R是被操作的表。例如,若要在T表(表4.1)中找出T1<20的行形成一个新表,则运算式为F(T)上式中F:T1<20,该选择运算的结果如表4.2所示。
表4.1 T表:下表列出相关数据。
| T1 | T2 | T3 | T4 | T5 |
|---|---|---|---|---|
| 1 | A1 | 3 | 3 | M |
| 2 | B1 | 2 | 0 | N |
| 3 | A2 | 12 | 12 | O |
| 5 | D5 | 10 | 24 | P |
| 0 | F2 | 1 | 4 | Q |
| 100 | A3 | 2 | 8 | N |
表4.2 σF(T)(F: T1<20):下表列出相关数据。
| T1 | T2 | T3 | T4 | T5 |
|---|---|---|---|---|
| 1 | A1 | 3 | 3 | M |
| 2 | B1 | 2 | 0 | N |
| 3 | A2 | 12 | 12 | O |
| 5 | D5 | 10 | 24 | P |
| 0 | F2 | 1 | 4 | Q |
说明:源文本此处所列数据与表4.1 T表完全相同(含T1=100的行),与选择条件F: T1<20不符;本表按F: T1<20对T表进行选择运算后给出结果,已剔除T1=100的行。
2.投影(Projection)投影也是单目运算,该运算从表中选出指定的属性值组成一个新表,记为ΠA(R)。其中,A是属性名(即列名)表,R是表名。例如,在T表中对T1、T2和T5投影,运算式为T1,T2,T5(T)该运算得到如表4.3所示的新表。
表4.3 ΠT1,T2,T5(T):下表列出相关数据。
| T1 | T2 | T5 |
|---|---|---|
| 1 | A1 | M |
| 2 | B1 | N |
| 3 | A2 | O |
| 5 | D5 | P |
| 0 | F2 | Q |
| 100 | A3 | N |
说明:源文本中各行顺序被打乱,此处按T1升序重排,投影结果与T表对应行一致。
3.连接(JOIN)连接是把两个表中的行按照给定的条件进行拼接而形成新表,记为。其中,R、S是被操作的表,F是条件。例如,若表A和B分别如表4.4和表4.5所示,则如表4.6所示,其中,F为T1=T3。
T2T1T2T1T2T1B2F6A1T5T4T3T5T4T3N02M31T5T4T3T2T1M31A1N02B2表4.4 A表表4.5 B表表4.6
表4.4 A表、表4.5 B表与表4.6连接结果的数据在源文本中连排且列序交错,无法高置信度切分,已保留原文并标注待人工还原。
数据库应用中最常用的是“自然连接”。进行自然连接运算要求两个表有共同属性(列),自然连接运算的结果表是在参与操作的两个表的共同属性上进行等值连接后,再去除重复的属性后所得的新表。自然连接运算记为,其中,R和S是参与运算的两个表。例如,若表A和B分别如表4.7和表4.8所示,则如表4.9所示。
表4.7 A表:下表列出相关数据。
| T1 | T2 | T3 |
|---|---|---|
| 20 | D2 | C2 |
| 5 | A1 | C2 |
| 10 | A1 | B1 |
表4.8 B表:下表列出相关数据。
| T1 | T4 | T5 | T6 |
|---|---|---|---|
| 20 | 0 | A2 | D1 |
| 1 | 100 | A1 | D1 |
| 5 | 10 | A2 | C2 |
| 100 | 2 | B2 | C1 |
表4.9 自然连接结果:下表列出相关数据。
| T1 | T2 | T3 | T4 | T5 | T6 |
|---|---|---|---|---|---|
| 5 | A1 | C2 | 10 | A2 | C2 |
| 20 | D2 | C2 | 0 | A2 | D1 |
当用户登录到SQL Server后,即被指定一个默认数据库,通常是master数据库。使用USE database_name语句可以选择当前要操作的数据库。其中,database_name是要选为当前数据库的数据库名。
例如,要选择PXSCJ为当前数据库,可以使用如下语句实现:USE PXSCJGO下面介绍SELECT语句,它是T-SQL的核心。
语法格式如下:[ WITH <common_table_expression>]SELECT [ ALL | DISTINCT ][ TOP expression [ PERCENT ] [ WITH TIES ] ]<select_list>[ INTO new_table ][ FROM table_source ][ WHERE search_condition ][ GROUP BY group_by_expression]
通过SELECT语句的<select_list>项组成结果表的列。
语法格式如下:<select_list> ::={*| { table_name | view_name | table_alias }.* | { column_name | [ ] expression | $IDENTITY | $ROWGUID }| udt_column_name [ { . | :: } { { property_name | field_name } | method_name(argument[,...n] ) } ]| expression[ [ AS ] column_alias ]| column_alias = expression}[ ,...n ]
1.选择所有列使用“*”表示选择一个表或视图中的所有列。
【例4.1】查询PXSCJ数据库中
查询PXSCJ数据库中XSB表的所有数据。 USE PXSCJ GO SELECT *FROM XSB GO 执行完后SQL Server Management Studio的结果窗口中将显示XSB表的所有数据。2.选择一个表中指定的列使用SELECT语句选择一个表中的某些列,各列名之间要以逗号分隔。其中,$IDENTITY表示选择标识列,$ROWGUID表示选择ROWGUIDCOL属性的全局标识列。如果在FROM子句中有多个表具有ROWGUIDCOL属性,则必须用特定的表名限定$ROWGUID,如T1.$ROWGUID。
【例4.2】查询PXSCJ数据库
查询PXSCJ数据库的XSB表中各个同学的姓名、专业和总学分。 USE PXSCJ GO SELECT姓名,专业,总学分FROM XSB GO SQL Server 2008中还能一次执行多个查询。【例4.3】查询
查询XSB表中计算机专业同学的学号、姓名和总学分,查询XSB表中所有列。SELECT学号,姓名,总学分FROM XSBWHERE专业= '计算机' GO SELECT *FROM XSB执行后在结果窗口中将分别列出两个查询语句的结果,如图4.1所示:图4.1一次执行多个查询
3.定义列别名当希望查询结果中的某些列或所有列显示时使用自己选择的列标题时,可以在列名之后使用AS子句来更改查询结果的列标题名。其中,column_alias是指定的列别名。
【例4.4】查询
查询XSB表中计算机系同学的学号、姓名和总学分,结果中各列的标题分别指定为number、name和mark。 USE PXSCJ GO SELECT学号AS number,姓名AS name,总学分AS mark FROM XSBWHERE专业= '计算机'执行结果如下:
更改查询结果中的列标题也可以使用column_alias=expression的形式。例如,SELECT number=学号, name =姓名, mark =总学分FROM XSBWHERE专业= '计算机'该语句的执行结果与上例的结果完全相同。当自定义的列标题中含有空格时,必须使用引号将标题括起来。
例如,SELECT 'Student number' =学号,姓名AS 'Student name', mark =总学分FROM XSBWHERE专业= '计算机'
4.替换查询结果中的数据在对表进行查询时,有时希望对所查询的某些列得到的是一种概念而不是具体的数据。例如,查询XSB表的总学分,希望知道的是学习的总体情况,这时,就可以用等级来替换总学分的具体数字。
要替换查询结果中的数据,则要使用查询中的CASE表达式,格式为CASEWHEN条件1 THEN表达式1WHEN条件2 THEN表达式2……ELSE表达式END
【例4.5】查询
查询XSB表中计算机系各同学的学号、姓名和总学分,对其总学分按以下规则进行替换:若总学分为空值,则替换为“尚未选课”;若总学分小于50,则替换为“不及格”;若总学分在50与52之间,则替换为“合格”;若总学分大于52,则替换为“优秀”。列标题更改为“等级”。 USE PXSCJ GO SELECT学号,姓名,等级=CASEWHEN总学分IS NULL THEN '尚未选课'WHEN总学分< 50 THEN '不及格'WHEN总学分>=50 and总学分<=52 THEN '合格' ELSE '优秀' ENDFROM XSBWHERE专业= '计算机' GO执行结果如下:
5.计算列值使用SELECT对列进行查询时,在结果中可以输出对列值计算后的值,即SELECT子句可使用表达式作为结果,格式为SELECT expression [ , expression ]
【例4.6】按
按120分计算成绩并显示学号为081101的学生的成绩情况。 USE PXSCJ GO SELECT学号,课程号,成绩120=成绩*1.20 FROM CJBWHERE学号= '081101'执行结果如下:6.消除结果集中的重复行对表只选择其某些列时,可能会出现重复行。例如,若对PXSCJ数据库的XSB表只选择专业和总学分,则出现多行重复的情况。
可以使用DISTINCT关键字消除结果集中的重复行,其格式是SELECT DISTINCT | ALL column_name [ , column_name…]关键字DISTINCT的含义是,对结果集中的重复行只选择一个,保证行的唯一性。
【例4.7】对PXSCJ数据库
对PXSCJ数据库的XSB表只选择专业和总学分,消除结果集中的重复行。 USE PXSCJ GO SELECT DISTINCT专业,总学分FROM XSB执行结果如下:7.限制结果集返回行数如果SELECT语句返回的结果集的行数非常多,那么可以使用TOP选项限制其返回的行数。TOP选项的基本格式为[ TOP expression [ PERCENT ] [ WITH TIES ] ]指示只能从查询结果集返回指定的第一组行或指定的百分比数目的行。expression可以是指定数目或百分比数目的行。
若带PERCENT关键字,则表示返回结果集的前expression%行。TOP子句可以用于SELECT、INSERT、UPDATE和DELETE语句中。
【例4.8】对PXSCJ数据库
对PXSCJ数据库的XSB表选择姓名、专业和总学分,返回结果集的前6行。 SELECT TOP 6姓名,专业,总学分FROM XSB8.选择用户定义数据类型列udt_column_name为要指定的用户定义类型列的名称。{ . | :: }指定用户定义类型的方法、属性或字段,将“.”用于实例(非静态)方法、属性或字段,“::”用于静态方法、属性或字段。property_name为udt_column_name的公共属性。
field_name为udt_column_name的公共数据成员。method_name是采用一个或多个参数的udt_column_name的公共方法。有关用户定义数据类型将在第5章中讨论。9.聚合函数SELECT子句中的表达式中还可以包含所谓的聚合函数。聚合函数常常用于对一组值进行计算,然后返回单个值。
聚合函数通常与GROUP BY子句一起使用。如果一个SELECT语句中有一个GROUP BY子句,则这个聚合函数对所有列起作用,如果没有,则SELECT语句只产生一行作为结果。SQL Server 2008所提供的聚合函数列于表4.10中。
说明函数名求组中值的平均值AVG返回对表中的行或表达式列表计算的二进制校验值,可用于检测表中行的更改BINARY_CHECKSUM返回在表的行上或在表达式列表上计算的校验值,用于生成哈希索引CHECKSUM返回组中值的校验值CHECKSUM_AGG求组中项数,返回int类型整数COUNT求组中项数,返回bigint类型整数COUNT_BIG产生一个附加的列GROUPING为聚合列列表中的每一行创建一个值以标识聚合级别GROUPING_ID求最大值MAX求最小值MIN返回表达式中所有值的和SUM返回给定表达式中所有值的统计标准偏差STDEV返回给定表达式中所有值的填充统计标准偏差STDEVP返回给定表达式中所有值的统计方差VAR返回给定表达式中所有值的填充统计方差VARP
表4.10聚合函数表:下表列出相关数据。
| 函数名 | 说明 |
|---|---|
| AVG | 求组中值的平均值 |
| BINARY_CHECKSUM | 返回对表中的行或表达式列表计算的二进制校验值,可用于检测表中行的更改 |
| CHECKSUM | 返回在表的行上或在表达式列表上计算的校验值,用于生成哈希索引 |
| CHECKSUM_AGG | 返回组中值的校验值 |
| COUNT | 求组中项数,返回int类型整数 |
| COUNT_BIG | 求组中项数,返回bigint类型整数 |
| GROUPING | 产生一个附加的列 |
| GROUPING_ID | 为聚合列列表中的每一行创建一个值以标识聚合级别 |
| MAX | 求最大值 |
| MIN | 求最小值 |
| SUM | 返回表达式中所有值的和 |
| STDEV | 返回给定表达式中所有值的统计标准偏差 |
| STDEVP | 返回给定表达式中所有值的填充统计标准偏差 |
| VAR | 返回给定表达式中所有值的统计方差 |
| VARP | 返回给定表达式中所有值的填充统计方差 |
下面对常用的聚合函数加以介绍。
(1)SUM和AVGSUM和AVG分别用于求表达式中所有值项的总和与平均值,语法格式为SUM /AVG ( [ ALL | DISTINCT ] expression )其中,expression是常量、列、函数或表达式,其数据类型只能是int、smallint、tinyint、bigint、decimal、numeric、float、real、money和smallmoney。
ALL表示对所有值进行运算,DISTINCT表示去除重复值,默认为ALL。SUM / AVG忽略NULL值。
【例4.9】求选修
求选修101课程的学生的平均成绩。 SELECT AVG(成绩) AS '课程101平均成绩' FROM CJBWHERE课程号= '101'使用聚合函数作为SELECT的选择列时,若不为其指定列标题,则系统将对该列输出标题“无列名”。
【例4.10】求学号
求学号为081101的同学所学课程的总成绩。 SELECT SUM(成绩) AS '课程总成绩' FROM CJBWHERE学号= '081101';结果为234。(2)MAX和MINMAX和MIN分别用于求表达式中所有值项的最大值与最小值,语法格式为MAX / MIN ( [ ALL | DISTINCT ] expression )其中,expression是常量、列、函数或表达式,其数据类型可以是数字、字符和时间日期类型。ALL、DISTINCT的含义及默认值与SUM/AVG函数相同。
MAX/MIN忽略NULL值。
【例4.11】求选修
求选修101课程的学生的最高分和最低分。 SELECT MAX(成绩) AS '课程101的最高分' , MIN(成绩) AS '课程101的最低分' FROM CJBWHERE课程号= '101'执行结果如下:(3)COUNTCOUNT用于统计组中满足条件的行数或总行数,格式为COUNT ( { [ ALL | DISTINCT ] expression } | * )其中,expression是一个表达式,其数据类型是除text、image或ntext之外的任何类型。
ALL、DISTINCT的含义及默认值与SUM/AVG函数相同,COUNT忽略NULL值。
【例4.12】求学生的总数
求学生的总数。 SELECT COUNT(*) AS '学生总数' FROM XSB学生总数为22,使用COUNT(*)时将返回检索行的总数目,不论其是否包含NULL值。【例4.13】统计备注不
统计备注不为空的学生数。 SELECT COUNT(备注) AS '备注不为空的学生数' FROM XSB;【例4.14】统计总学分
统计总学分在50分以上的人数。 SELECT COUNT(总学分) AS '总学分在50分以上的人数' FROM XSBWHERE总学分>50;执行结果为2。【例4.15】求选修了课程
求选修了课程的学生总数。 SELECT COUNT(DISTINCT学号) FROM CJBCOUNT_BIG函数的格式、功能与COUNT函数都相同,区别仅在于COUNT_BIG返回bigint类型值。在SQL Server 2008中,选择行是通过在SELECT语句的WHERE子句中指定选择的条件来实现的。这一节将详细讨论WHERE子句中查询条件的构成。WHERE子句必须紧跟在FROM子句之后,其基本格式为WHERE <search_condition>其中,search_condition为查询条件。
<search_condition>::={ [ NOT ] <precdicate> | (<search_condition> ) }[ { AND | OR } [ NOT ] { <predicate> | (<search_condition>) } ][ ,…n ]
其中,<predicate>为判定运算,结果为TRUE、FALSE或UNKNOWN。NOT表示对判定的结果取反,AND用于组合两个条件,两个条件都为TRUE时值才为TRUE。OR也用于组合两个条件,两个条件有一个条件为TRUE时值就为TRUE。
<predicate>::={expression { = | < | <= | > | >= | <> | != | !< | !> } expression| match_expression [ NOT ] LIKE pattern [ ESCAPE Escape_character ]| expression [ NOT ] BETWEEN expression AND expression| expression IS [ NOT ] NULL| CONTAINS ( { column | * }, '<contains_search_condition>')| FREETEXT ({ column | * }, 'freetext_string')| expression [ NOT ] IN ( subquery | expression [,…n] )| expression { = | < | <= | > | >= | <> | != | !< | !> } { ALL | SOME | ANY } ( subquery )| EXIST ( subquery )}
1.表达式比较比较运算符用于比较两个表达式值,共有9个,分别是=(等于)、<(小于)、<=(小于等于)、>(大于)、>=(大于等于)、<>(不等于)、!=(不等于)、!<(不小于)、!>(不大于)。
比较运算的格式为expression { = | < | <= | > | >= | <> | != | !< | !> } expression其中,expression是除text、ntext和image以外类型的表达式。
当两个表达式值均不为空值(NULL)时,比较运算返回逻辑值TRUE(真)或FALSE(假)。而当两个表达式值中有一个为空值或都为空值时,比较运算将返回UNKNOWN。
【例4.16】查询PXSCJ数据库
查询PXSCJ数据库XSB表中学号为081101的同学的情况。 USE PXSCJ GO SELECT姓名,学号,总学分FROM XSBWHERE学号='081101';执行结果如下:【例4.17】查询
查询XSB表中总学分大于50的同学的情况。SELECT姓名,学号,出生时间,总学分FROM XSBWHERE总学分>50;执行结果如下:【例4.18】查询
查询XSB表中通信工程专业总学分大于等于42的同学的情况。 USE PXSCJ GO SELECT *FROM XSBWHERE专业= '通信工程' AND总学分>= 422.模式匹配LIKE谓词用于指出一个字符串是否与指定的字符串相匹配,返回逻辑值TRUE或FALSE。LIKE谓词表达式的格式为match_expression [ NOT ] LIKE pattern [ ESCAPE Escape_character ]说明如下。match_expression:匹配表达式,一般为字符串表达式,在查询语句中可以是列名。
pattern:在match_expression中的搜索模式串。在搜索模式串中可以使用通配符,表4.11列出了LIKE谓词可以使用的通配符及其说明。说明通配符代表0个或多个字符%代表单个字符_(下画线)指定范围(如[a-f]、[0-9])或集合(如[abcdef])中的任何单个字符[ ]指定不属于范围(如[^a-f]、[^0-9])或集合(如[^abcdef])的任何单个字符[^]
表4.11通配符列表:下表列出相关数据。
| 通配符 | 说明 |
|---|---|
| % | 代表0个或多个字符 |
| _(下画线) | 代表单个字符 |
| [ ] | 指定范围(如[a-f]、[0-9])或集合(如[abcdef])中的任何单个字符 |
| [^] | 指定不属于范围(如[^a-f]、[^0-9])或集合(如[^abcdef])的任何单个字符 |
Escape_character:转义字符,应为有效的SQL Server字符,Escape_character没有默认值,且必须为单个字符。当模式串中含有与通配符相同的字符时,应通过该字符前的转义字符指明其为模式串中的一个匹配字符。使用ESCAPE可指定转义符。NOT LIKE:使用NOT LIKE与LIKE的作用相反。
使用带%通配符的LIKE时,若使用LIKE进行字符串比较,则模式字符串中的所有字符都有意义,包括起始或尾随空格。
【例4.19】查询
查询XSB表中姓“王”且单名的学生情况。 SELECT *FROM XSBWHERE姓名LIKE '王_ '执行结果如下:【例4.20】查询
查询XSB表中学号倒数第3个数字为1,且倒数第1个数在1~5之间的学生学号、姓名及专业。SELECT学号,姓名,专业FROM XSBWHERE学号LIKE '%1_[12345]'如果需要查找一个通配符,则必须使用一个转义字符。【例4.21】查询
查询XSB表中名字包含下划线的学生学号和姓名。SELECT学号,姓名FROM XSBWHERE学号LIKE '%#_%' ESCAPE '#'3.范围比较用于范围比较的关键字有两个:BETWEEN和IN。当要查询的条件是某个值的范围时,可以使用BETWEEN关键字。
BETWEEN关键字指出查询范围,格式为:expression [ NOT ] BETWEEN expression1 AND expression2当不使用NOT时,若表达式expression的值在表达式expression1与expression2之间(包括这两个值),则返回TRUE,否则返回FALSE;
当使用NOT时,返回值刚好相反。使用IN关键字可以指定一个值表,值表中列出所有可能的值,当与值表中的任一个匹配时,即返回TRUE,否则返回FALSE。使用IN关键字指定值表的格式为:expression IN ( expression [,…n])
【例4.22】查询
查询XSB表中不在1989年出生的学生情况。SELECT学号,姓名,专业,出生时间FROM XSBWHERE出生时间NOT BETWEEN '1989-1-1' and '1989-12-31'【例4.23】查询
查询XSB表中专业为“计算机”、“通信工程”或“无线电”的学生情况。 SELECT *FROM XSBWHERE专业IN ('计算机', '通信工程', '无线电')该语句与下列语句等价: SELECT *FROM XSBWHERE专业= '计算机' or专业= '通信工程' or专业='无线电'4.空值比较当需要判定一个表达式的值是否为空值时,使用IS NULL关键字,格式为:expression IS [ NOT ] NULL当不使用NOT时,若表达式expression的值为空值,则返回TRUE,否则返回FALSE;当使用NOT时,结果刚好相反。
【例4.24】查询总学分尚不定
查询总学分尚不定的学生情况。 SELECT *FROM XSBWHERE总学分IS NULL5.CONTAINS谓词下面介绍如何利用图形化界面向导的方式来新建全文索引,其主要步骤如下。第1步:要建立全文索引,首先要启动全文搜索服务,这项服务默认是禁用的。启动的方法是:打开“SQL Server配置管理器”窗口,进入“SQL Full-Text FilterDaemon Launcher”服务的属性对话框。
选择“服务”选项卡,将“启动模式”设置为“自动”,如图4.2所示。设置完后单击“应用”按钮,再选择“登录”选项卡,将内置账户设置为本地账户,如local system,如图4.3所示,单击“启动”按钮启动全文搜索,最后单击“确定”按钮关闭窗口。图4.2更改服务启动模式图4.3启动全文搜索
第2步:创建全文目录。在对象资源管理器中展开数据库“PXSCJ”,选择“存储”目录下的“全文目录”,右击鼠标,选择“新建全文目录”选项。在弹出的“新建全文目录-PXSCJ”窗口中填写全文目录名称,如fulltext,如图4.4所示,单击“确定”按钮。图4.4创建全文目录
第3步:在全文目录中注册需要全文索引的表。在“全文目录”目录下右击刚刚新建的全文目录“fulltext”,选择“属性”菜单项,进入fulltext的属性窗口。选择“表/视图”选项卡,选择需要全文索引的表,如“dbo.XSB”,单击按钮。
选择完需要全文索引的表后,在“合格列”栏中会显示能够进行全文索引的列,选择需要的列,如图4.5所示,单击“确定”按钮。图4.5在全文目录中注册需要全文索引的表
下面继续讨论CONTAINS谓词的使用,CONTAINS谓词的语法格式如下。
CONTAINS ( { column | * } , '<contains_search_condition>' [ , LANGUAGElanguage_term ])其中,column表示在指定的列中搜索,可以指定多个列,类型为char、varchar、nchar、nvarchar、text、ntext、image、xml和varbinary(max)的列是可进行全文搜索的有效列。
*表示在所有列中搜索,language_term表示用户查询时所用的语言。<contains_search_condition>指定要在column_name中搜索的文本和匹配条件。
< contains_search_condition > ::={< simple_term >| < prefix_term >| < generation_term >| < proximity_term >| < weighted_term >}| {( < contains_search_condition > ) [ { < AND > | < AND NOT > | < OR > } ]< contains_search_condition > [ ...n ]}
说明如下。<simple_term>:用于说明搜索的是单词还是短语,格式为:word | "phrase"其中,word为单词,即不含空格和标点符号的字符串;短语是含一个或多个空格的字符串。如果搜索的是短语,则需要用双引号将其括起来。
<prefix_term>:给出了要搜索的单词或短语必须匹配的前缀,其格式为:{ "word*" | "phase*"}其中,word为单词,phase为短语,当查询的串是短语时,需用双引号定界。<generation_term>:说明搜索包含原词的派生词,所谓派生词是指原词的名词单、复数形式或动词的各种时态等。
格式为:FORMSOF ( { INFLECTIONAL | THESAURUS } , < simple_term > [ ,...n ] )INFLECTIONAL选项表示指定要对指定的简单字词使用与语言相关的词干分析器。THESAURUS选项表示指定使用对应于列全文语言或指定的查询语言的同义词库。
<proximity_term>:表示搜索包含NEAR或~运算符左右两边的词或短语。格式为:{ <simple_term> | <prefix_term> } { { NEAR | ~ } { <simple_term> |<prefix_term> }[…n]
<weight_term>:指明本语句是加权搜索,即查询的数据与给定的权重进行加权匹配。
格式为:ISABOUT( { {< simple_term >| < prefix_term >| < generation_term >| < proximity_term >}[ WEIGHT ( weight_value ) ]} [ ,...n ])其中,weight_value是一个0~1之间的数,表示权重。
【例4.25】使用CONTAINS谓词搜索
使用CONTAINS谓词搜索XSB表中包含字符“工程”的所有行。 USE PXSCJ GO SELECT *FROM XSBWHERE CONTAINS(*,'工程')执行结果如下:6.FREETEXT谓词与CONTAINS谓词类似,FREETEXT谓词也用于在一个表中搜索单词或短语,并要求表已建立全文索引。
格式为FREETEXT ( { column| column _list | * }, 'freetext_string' [ , LANGUAGElanguage_term ] )其中,freetext_string是要搜索的字符串。FREETEXT的查询精度没有CONTAINS高,并不要求对它们进行严格的模式匹配。
FREETEXT对所查询的串也没有写法要求,因此FREETEXT也称为自由式查询。
【例4.26】使用FREETEXT谓词搜索
使用FREETEXT谓词搜索XSB表中包含字符“李”的所有行。 SELECT *FROM XSBWHERE FREETEXT(*,'李')7.子查询T-SQL允许SELECT多层嵌套使用,用来表示复杂的查询。子查询除了可以用在SELECT语句中,还可以用在INSERT、UPDATE及DELETE语句中。子查询通常与IN、EXIST谓词及比较运算符结合使用。
(1)IN子查询IN子查询用于进行一个给定值是否在子查询结果集中的判断,格式为:expression [ NOT ] IN ( subquery )其中,subquery是子查询。当表达式expression与子查询subquery的结果表中的某个值相等时,IN谓词返回TRUE,否则返回FALSE;若使用了NOT,则返回的值刚好相反。
【例4.27】查找选修了课程号
查找选修了课程号为206的课程的学生情况。在“查询分析器”窗口中输入并执行如下查询脚本: USE PXSCJ GO SELECT *FROM XSBWHERE学号IN( SELECT学号FROM CJBWHERE课程号= '206')在执行包含子查询的SELECT语句时,系统先执行子查询,产生一个结果表,再执行查询。本例中,先执行上面括号里面的子查询:SELECT学号FROM CJB WHERE课程名= '206'【例4.28】查找未选修离散数学
查找未选修离散数学的学生情况。 SELECT *FROM XSBWHERE学号NOT IN(SELECT学号FROM CJBWHERE课程号IN(SELECT课程号FROM KCBWHERE课程名= '离散数学'))(2)比较子查询这种子查询可以认为是IN子查询的扩展,它使表达式的值与子查询的结果进行比较运算,格式为expression { < | <= | = | > | >= | != | <> | !< | !> } { ALL | SOME | ANY } ( subquery )其中,expression为要进行比较的表达式,subquery是子查询。
ALL、SOME和ANY说明对比较运算的限制。ALL指定表达式要与子查询结果集中的每个值都进行比较,当表达式与每个值都满足比较的关系时,才返回TRUE,否则返回FALSE;SOME或ANY表示表达式只要与子查询结果集中的某个值满足比较的关系,就返回TRUE,否则返回FALSE。
【例4.29】查找选修了离散数学
查找选修了离散数学的学生学号。SELECT学号FROM CJBWHERE课程号=(SELECT课程号FROM KCBWHERE课程名='离散数学');【例4.30】查找比所
查找比所有计算机系的学生年龄都大的学生。 SELECT *FROM XSBWHERE出生时间<ALL(SELECT出生时间FROM XSBWHERE专业= '计算机')执行结果如下:
【例4.31】查找
查找206号课程成绩不低于101号课程最低成绩的学生学号。SELECT学号FROM CJBWHERE课程号= '206' AND成绩!< ANY(SELECT成绩FROM CJBWHERE课程号= '101')(3)EXISTS子查询EXISTS谓词用于测试子查询的结果是否为空表,若子查询的结果集不为空,则EXISTS返回TRUE,否则返回FALSE。EXISTS还可与NOT结合使用,即NOT EXISTS,其返回值与EXISTS刚好相反。其格式为[ NOT ] EXISTS ( subquery )
【例4.32】查找选修
查找选修206号课程的学生姓名。SELECT姓名FROM XSBWHEREEXISTS(SELECT *FROM CJBWHERE学号= XSB.学号AND课程号= '206')其处理过程如下:首先查找外层查询中XSB表的第一行,根据该行的学号列值处理内层查询,若结果不为空,则WHERE条件为真,就把该行的姓名值取出作为结果集的一行;然后再找XSB表的第2,3…行,重复上述处理过程直到XSB表的所有行都查找完为止。
【例4.33】查找选修了全部课程
查找选修了全部课程的同学的姓名。SELECT姓名FROM XSBWHERE NOT EXISTS(SELECT *FROM KCBWHERE NOT EXISTS(SELECT *FROM CJBWHERE学号=XSB.学号AND课程号=KCB.课程号))另外,子查询还可以用在SELECT语句的其他子句中,如FROM子句。SELECT关键字后面也可以定义子查询。
【例4.34】从
从XSB表中查找所有女学生的姓名、学号及其与081101号学生的年龄差距。SELECT学号,姓名, YEAR(出生时间)-YEAR(( SELECT出生时间FROM XSBWHERE学号='081101') ) AS年龄差距FROM XSBWHERE性别=0执行结果如下:SELECT的查询对象由FROM子句指定,其格式为[ FROM {<table_source>} [,…n] ]其中,table_source指出了要查询的表或视图。
<table_source> ::={table_or_view_name [ [ AS ] table_alias ][ WITH ( < table_hint > [ [ , ]...n ] ) ]| rowset_function [ [ AS ] table_alias ][ ( bulk_column_alias [ ,...n ] ) ]| user_defined_function [ [ AS ] table_alias ]| OPENXML <openxml_clause>| derived_table [ AS ] table_alias [ ( column_alias [ ,...n ] ) ]| <joined_table>| <pivoted_table>| <unpivoted_table>}
1.table_or_view_nametable_or_view_name指定SELECT语句要查询的表或视图,表和视图可以是一个或多个,有关视图的内容在4.3节中介绍。
【例4.35】查找表
查找表KCB中101号课程的开课学期。 USE PXSCJ GO SELECT开课学期FROM KCBWHERE课程号= '101'查询结果为1。【例4.36】查找081101号学生计算机基础课
查找081101号学生计算机基础课的成绩。SELECT成绩FROM CJB, KCBWHERE CJB.课程号=KCB.课程号AND学号='081101'AND课程名='计算机基础'【例4.37】查找选修了学号
查找选修了学号为081102的同学所选修的全部课程的同学的学号。 SELECT DISTINCT学号FROM CJB AS CJ1 WHERE NOT EXISTS(SELECT *FROM CJB AS CJ2 WHERE CJ2.学号= '081102' AND NOT EXISTS(SELECT *FROM CJB AS CJ3 WHERE CJ3.学号=CJ1.学号AND CJ3.课程号= CJ2.课程号))2.rowset_functionrowset_function是一个行集函数,行集函数通常返回一个表或视图。bulk_column_alias是替代结果集内列名的可选别名。主要的行集函数有CONTAINSTABLE、FREETEXTTABLE、OPENDATASOURCE、OPENQUERY、OPENROWSET和OPENXML。
(3)OPENDATASOURCE函数。该函数使用户连接到服务器。
格式为:OPENDATASOURCE ( provider_name , init_string )其中,provider_name是用于访问数据源OLE DB访问接口的PROGID的名称,init_string是连接字符串,这些字符串将要传递给目标提供程序的IDataInitialize接口。(4)OPENQUERY函数。
该函数在给定的链接服务器(一个OLE DB数据源)上执行指定的直接传递查询,返回查询的结果集。(5)OPENROWSET函数。该函数与OPENQUERY函数功能相同,只是语法格式不同。(6)OPENXML函数。OPENXML通过XML文档提供行集视图。
3.user_defined_functionuser_defined_function是表值函数,所谓表值函数就是返回一个表的用户自定义函数,有关用户自定义函数的内容将在第5章中介绍。
4.derived_table子查询可以用在FROM子句中,derived_table表示由子查询中SELECT语句的执行而返回的表,但必须使用AS关键字为子查询产生的中间表定义一个别名。
【例4.38】从
从XSB表中查找总学分大于50的男同学的姓名和学号。SELECT姓名,学号,总学分FROM ( SELECT姓名,学号,性别,总学分FROM XSBWHERE总学分>50) AS STUDENTWHERE性别=1;执行结果如下:【例4.39】在
在XSB表中查找1990年1月1日以前出生的学生的姓名和专业,分别使用别名stu_name和speciality表示。 SELECT m.stu_name, m.speciality FROM ( SELECT * FROM XSB WHERE出生时间<'19900101' ) AS m( num,stu_name, sex, birthday, speciality,score, mem )执行结果如下:5.pivoted_table和unpivoted_table<pivoted_table>的格式如下:<pivoted_table> ::=table_source PIVOT <pivot_clause> [AS] table_alias其中,<pivot_clause> ::=( aggregate_function ( value_column ) FOR pivot_column IN (<column_list>) )
【例4.40】查找
查找XSB表中1990年1月1日以前出生的学生的姓名和总学分,并列出其属于计算机专业还是通信工程专业的情况,1表示是,0表示否。SELECT姓名,总学分,计算机,通信工程FROM XSBPIVOT(COUNT(学号)FOR专业IN(计算机,通信工程)) AS pvtWHERE出生时间<'1990-01-01'执行结果如下:<unpivoted_table>格式如下:<unpivoted_table> ::=table_source UNPIVOT <unpivot_clause> table_alias其中,<unpivot_clause> ::=( value_column FOR pivot_column IN ( <column_list> ) )
【例4.41】将
将KCB表中的开课学期和学分列转换为行输出。SELECT课程号,课程名,选项,内容FROM KCBUNPIVOT(内容FOR选项IN(学分,开课学期))unpvt执行结果如下:1.连接谓词可以在SELECT语句的WHERE子句中使用比较运算符给出连接条件对表进行连接,将这种表示形式称为连接谓词表示形式。
【例4.42】查找PXSCJ数据库
查找PXSCJ数据库每个学生的情况以及选修的课程情况。 USE PXSCJ GO SELECT XSB.* , CJB.*FROM XSB , CJBWHERE XSB.学号= CJB.学号结果表将包含XSB表和CJB表的所有列。【例4.43】自然连接查询
自然连接查询。 SELECT XSB.* , CJB.课程号, CJB.成绩FROM XSB , CJBWHERE XSB.学号= CJB.学号本例所得的结果表包含以下字段:学号、姓名、性别、出生时间、专业、总学分、备注、课程号、成绩。若选择的字段名在各个表中是唯一的,则可以省略字段名前的表名。例如,本例的SELECT语句也可写为: SELECT XSB.* ,课程号,成绩FROM XSB , CJBWHERE XSB.学号= CJB.学号【例4.44】查找选修
查找选修了206号课程且成绩在80分以上的学生姓名及成绩。SELECT姓名,成绩FROM XSB , CJBWHERE XSB.学号= CJB.学号AND课程号= '206' AND成绩>= 80执行结果如下:【例4.45】查找选修
查找选修了“计算机基础”课程且成绩在80分以上的学生学号、姓名、课程名及成绩。 SELECT XSB.学号,姓名,课程名,成绩FROM XSB , KCB , CJBWHERE XSB.学号= CJB.学号AND KCB.课程号= CJB.课程号AND课程名= '计算机基础'AND成绩>= 80执行结果如下:2.以JOIN关键字指定的连接T-SQL扩展了以JOIN关键字指定连接的表示方式,使表的连接运算能力有了增强。FROM子句的<joined_table>表示将多个表连接起来。格式如下。
<joined_table> ::={<table_source> <join_type> <table_source> ON <search_condition>| <table_source> CROSS JOIN <table_source>| left_table_source { CROSS | OUTER } APPLY right_table_source| [ ( ) <joined_table> [ ] ]}
说明如下。<table_source>:准备要连接的表。<join_type>表示连接类型。
<join_type>的格式为<join_type> ::=[ { INNER | { { LEFT | RIGHT | FULL } [ OUTER ] } } [ <join_hint> ] ]JOIN其中,INNER表示内连接,OUTER表示外连接,<join_hint>是连接提示。
ON:用于指定连接条件,<search_condition>为连接的条件。APPLY运算符:使用APPLY运算符可以为实现查询操作的外部表表达式返回的每个行调用表值函数。left_table_source为外部表值表达式,right_table_source为表值函数。
通过对right_table_source求值来获得left_table_source每一行的计算结果,生成的行被组合起来作为最终输出。APPLY运算符生成的列的列表是left_table_source中的列集,后跟right_table_source返回的列的列表。CROSS APPLY仅返回外部表中通过表值函数生成结果集的行。
OUTER APPLY既返回生成结果集的行,也返回不生成结果集的行。CROSS JOIN:表示交叉连接。
(1)内连接。指定了INNER关键字的连接是内连接,内连接按照ON所指定的连接条件合并两个表,返回满足条件的行。
【例4.46】查找PXSCJ数据库
查找PXSCJ数据库每个学生的情况以及选修的课程情况。 SELECT *FROM XSB INNER JOIN CJBON XSB.学号=CJB.学号执行的结果将包含XSB表和CJB表的所有字段(不去除重复字段——学号)。内连接是系统默认的,可以省略INNER关键字。使用内连接后仍可使用WHERE子句指定条件。【例4.47】用FROM子句
用FROM子句的JOIN关键字表达下列查询:查找选修了206号课程且成绩在80分以上的学生姓名及成绩。SELECT姓名,成绩FROM XSB JOIN CJBON XSB.学号= CJB.学号WHERE课程号= '206' AND成绩>=80执行结果如下:【例4.48】用FROM子句
用FROM子句的JOIN关键字表达下列查询:查找选修了“计算机基础”课程且成绩在80分以上的学生学号、姓名、课程名及成绩。 SELECTXSB.学号,姓名,课程名,成绩FROM XSB JOIN CJB JOIN KCBON CJB.课程号= KCB.课程号ON XSB.学号= CJB.学号WHERE课程名= ‘计算机基础’ AND成绩>=80若要在一个表中查找具有相同列值的行,则可以使用自连接。使用自连接时需为表指定两个别名,且对所有列的引用均要用别名限定。【例4.49】查找不同课程成绩相同
查找不同课程成绩相同的学生的学号、课程号和成绩。 SELECT a.学号, a.课程号, b.课程号, a.成绩FROM CJB a JOIN CJB b ON a.成绩=b.成绩AND a.学号=b.学号AND a.课程号!=b.课程号执行结果如下:(2)外连接。指定了OUTER关键字的为外连接,外连接的结果表不但包含满足连接条件的行,还包括相应表中的所有行。外连接包括以下三种。左外连接(LEFT OUTER JOIN):结果表中除了包括满足连接条件的行外,还包括左表的所有行;右外连接(RIGHT OUTER JOIN):结果表中除了包括满足连接条件的行外,还包括右表的所有行;
完全外连接(FULL OUTER JOIN):结果表中除了包括满足连接条件的行外,还包括两个表的所有行。其中的OUTER关键字均可省略。
【例4.50】查找所
查找所有学生情况,以及他们选修的课程号,若学生未选修任何课,也要包括其情况。 SELECT XSB.* ,课程号FROM XSB LEFT OUTER JOIN CJBON XSB.学号= CJB.学号本例执行时,若有学生未选任何课程,则结果表中相应行的课程号字段值为NULL。【例4.51】查找被选修
查找被选修了的课程的选修情况和所有开设的课程名。 SELECT CJB.* ,课程名FROM CJB RIGHT JOIN KCBON CJB.课程号= KCB.课程号(3)交叉连接。交叉连接实际上是将两个表进行笛卡尔积运算,结果表是由第一个表的每一行与第二个表的每一行拼接后形成的表,因此结果表的行数等于两个表的行数之积。
【例4.52】列出学生所
列出学生所有可能的选课情况。SELECT学号,姓名,课程号,课程名FROM XSB CROSS JOIN KCB交叉连接也可以使用WHERE子句进行条件限定。1.非ISO标准的GROUP BY子句语法格式如下。[ GROUP BY [ ALL ] group_by_expression [,…n][ WITH { CUBE | ROLLUP } ] ]说明如下。group_by_expression:用于分组的表达式,其中通常包含字段名。指定ALL将显示所有组。
使用GROUP BY子句后,SELECT子句中的列表中只能包含在GROUP BY中指出的列或在聚合函数中指定的列。WITH:指定CUBE或ROLLUP操作符,CUBE或ROLLUP与聚合函数一起使用,在查询结果中增加附加记录。
【例4.53】将PXSCJ数据库中
将PXSCJ数据库中各专业输出。SELECT专业FROM XSBGROUP BY专业执行结果如下:【例4.54】求各专业的学生数
求各专业的学生数。SELECT专业, COUNT(*) AS '学生数' FROM XSBGROUP BY专业执行结果如下:【例4.55】求被选修
求被选修的各门课程的平均成绩和选修该课程的人数。SELECT课程号, AVG(成绩) AS '平均成绩' , COUNT(学号) AS '选修人数' FROM CJBGROUP BY课程号执行结果如下:【例4.56】在PXSCJ数据库上产生一个结果集
在PXSCJ数据库上产生一个结果集,包括每个专业的男生、女生人数、总人数及学生总人数。SELECT专业,性别, COUNT(*) AS '人数' FROM XSBGROUP BY专业,性别WITH ROLLUP执行结果如下:可以将上述语句与不带ROLLUP操作符的GROUP BY子句的执行情况做一个比较:SELECT专业,性别, COUNT(*) AS '人数'FROM XSBGROUP BY专业,性别执行结果如下:
【例4.57】在PXSCJ数据库上产生一个结果集
在PXSCJ数据库上产生一个结果集,包括每个专业的男生、女生人数、总人数,以及男生总数、女生总数、学生总人数。SELECT专业,性别, COUNT(*) AS '人数' FROM XSBGROUP BY专业,性别WITH CUBE执行结果如下:使用带有CUBE或ROLLUP的GROUP BY子句时,SELECT子句的列表还可以是聚合函数GROUPING。若需要标志结果表中哪些行是由CUBE或ROLLUP添加的而哪些行不是,则可使用GROUPING函数作为输出列。
【例4.58】统计各专业男生
统计各专业男生、女生人数及学生总人数,标志汇总行。SELECT专业,性别, COUNT(*) AS '人数',GROUPING(专业) AS 'spec', GROUPING(性别) AS 'sx' FROM XSBGROUP BY专业,性别WITH CUBE执行结果如下:2.ISO标准的GROUP BY子句语法格式如下。
GROUP BY{<column_expression>| ROLLUP ( <composite element list> )| CUBE (<composite element list>>)| GROUPING SETS ( <grouping set item list>)}说明如下。
<column_expression>:指定分组的字段名表达式。ROLLUP():生成简单的GROUP BY聚合行、小计行或超聚合行,还生成一个总计行,返回的分组数等于<composite element list>中的表达式数加一,功能与非ISO标准语法中的WITH ROLLUP子句类似。
CUBE():生成简单的GROUP BY聚合行、ROLLUP超聚合行和交叉表格行。CUBE针对<composite element list>中表达式的所有排列输出一个分组。生成的分组数等于2n,其中,n为<composite element list>中的表达式数,功能与WITHCUBE子句类似。
GROUPING SETS():在一个查询中指定数据的多个分组。仅聚合指定组,而不聚合由CUBE或ROLLUP生成的整组聚合。其结果与针对指定的组执行UNION ALL运算等效。GROUPING SETS可以包含单个元素或元素列表。
设置数据库的兼容级别可以使用ALTER DATABASE语句,语法格式如下:ALTER DATABASE database_nameSET COMPATIBILITY_LEVEL = { 80 | 90 | 100 }80、90和100分别代表SQL Server 2000、SQL Server 2005和SQL Server 2008。
所以需要将PXSCJ数据库的兼容级别设置成100,使用如下语句:ALTER DATABASE PXSCJSET COMPATIBILITY_LEVEL=100
另外,还可以使用界面方式完成,方法如下:打开数据库PXSCJ的“属性”窗口,选择“选项”选项卡,在窗口右边的“兼容级别”下拉框中选择“SQL Server 2008(100)”,如图4.6所示,单击“确定”按钮即可。图4.6设置数据库兼容级别
【例4.59】在PXSCJ数据库上产生一个结果集
在PXSCJ数据库上产生一个结果集,包括每个专业的男生、女生人数、总人数及学生总人数。SELECT专业,性别, COUNT(*) AS '人数' FROM XSBGROUP BY ROLLUP(专业,性别)执行结果如下:【例4.60】在PXSCJ数据库上产生一个结果集
在PXSCJ数据库上产生一个结果集,包括每个专业的男生、女生人数、总人数,以及男生总数、女生总数、学生总人数。SELECT专业,性别, COUNT(*) AS '人数' FROM XSBGROUP BY CUBE(专业,性别)执行结果如下:【例4.61】生成一个结果集
生成一个结果集,分别根据专业和性别对人数进行聚合。SELECT专业,性别, COUNT(*) AS '人数' FROM XSBGROUP BY GROUPING SETS(专业,性别)执行结果如下:例如,查找PXSCJ数据库中平均成绩在85分以上的学生,就是在CJB表上按学号分组后筛选出符合平均成绩大于等于85的学生。
HAVING子句的格式为[ HAVING <search_condition> ]其中,search_condition为查询条件,与WHERE子句的查询条件类似,不过HAVING子句中可以使用聚合函数,而WHERE子句中不可以。
【例4.62】查找平均成绩
查找平均成绩在85分以上的学生的学号和平均成绩。 USE PXSCJ GO SELECT学号, AVG(成绩) AS '平均成绩' FROM CJBGROUP BY学号HAVING AVG(成绩) > =85执行结果如下:【例4.63】查找选修课程超过
查找选修课程超过2门且成绩都在80分以上的学生的学号。SELECT学号FROM CJBWHERE成绩>= 80GROUP BY学号HAVING COUNT(*) > 2【例4.64】查找通信工程专业平均成绩
查找通信工程专业平均成绩在85分以上的学生的学号和平均成绩。SELECT学号, AVG(成绩) AS '平均成绩' FROM CJBWHERE学号IN(SELECT学号FROM XSBWHERE专业= '通信工程')GROUP BY学号HAVING AVG(成绩) > =85执行结果如下:在应用中经常要对查询的结果排序输出,如将学生成绩由高到低排序。在SELECT语句中,使用ORDER BY子句对查询结果进行排序。ORDER BY子句的格式为[ ORDER BY{order_by_expression[ COLLATE collation_name ][ ASC | DESC ]} [ ,...n ]]
【例4.65】将通信工程专业
将通信工程专业的学生按出生时间先后顺序排序。 SELECT *FROM XSBWHERE专业= '通信工程' ORDER BY出生时间【例4.66】将计算机专业学生
将计算机专业学生的“计算机基础”课程成绩按降序排列。SELECT姓名,课程名,成绩FROM XSB, KCB, CJBWHERE XSB.学号= CJB.学号AND CJB.课程号= KCB.课程号AND课程名= '计算机基础'AND专业= '计算机' ORDER BY成绩DESCORDER BY子句可以与COMPUTE BY子句一起使用,在对结果排序的同时还产生附加的汇总行。COMPUTE子句用于分类汇总,将产生额外的汇总行。格式为[ COMPUTE {聚合函数名(expression)} [ ,…n ] [ BY expression [ ,…n ] ] ]【例4.67】查找通信工程专业学生
查找通信工程专业学生的学号、姓名、出生时间,并产生一个学生总人数行。SELECT学号,姓名,出生时间FROM XSBWHERE专业= '通信工程'COMPUTE COUNT(学号)执行结果如下:【例4.68】将学生按专业排序
将学生按专业排序,并汇总各专业人数和平均学分。SELECT学号,姓名,出生时间,总学分FROM XSBORDER BY专业COMPUTE COUNT(学号), AVG(总学分) BY专业执行结果如下:1.INTO使用INTO子句可以将SELECT查询所得的结果保存到一个新建的表中。INTO子句的格式为[ INTO new_table ]其中,new_table是要创建的新表名。
包含INTO子句的SELECT语句执行后所创建的表的结构由SELECT所选择的列决定,新创建的表中的记录由SELECT的查询结果决定,若SELECT的查询结果为空,则创建一个只有结构而没有记录的空表。
【例4.69】由
由XSB表创建“计算机系学生”表,包括学号和姓名。SELECT学号,姓名INTO计算机系学生FROM XSBWHERE专业= '计算机'2.UNION使用UNION子句可以将两个或多个SELECT查询的结果合并成一个结果集,其格式为{ <query specification> | (<query expression> ) }UNION [ A LL ] <query specification> | (<query expression> )[ UNION [ A LL ] <query specification> | (<query expression> ) […n] ]其中,<query specification>和<query expression>都是SELECT查询语句。
使用UNION组合两个查询的结果集的基本规则是:
【例4.70】查找学号
查找学号为081101和学号为081210的两位同学的信息。 SELECT *FROM XSBWHERE学号= '081101' UNION ALLSELECT *FROM XSBWHERE学号= '081210'执行结果如下:3.EXCEPT和INTERSECTEXCEPT和INTERSECT用于比较两个查询的结果,返回非重复值。
语法格式如下:{ <query_specification> | ( <query_expression> ) }{ EXCEPT | INTERSECT }{ <query_specification> | ( <query_expression> ) }其中,<query specification>和<query expression>都是SELECT查询语句。
使用EXCEPT和INTERSECT比较两个查询的规则和UNION语句一样。EXCEPT从EXCEPT关键字左边的查询中返回右边查询没有找到的所有非重复值。INTERSECT返回INTERSECT关键字左右两边的两个查询都返回的所有非重复值。EXCEPT或INTERSECT返回的结果集的列名与关键字左侧的查询返回的列名相同。
【例4.71】查找专业
查找专业为计算机但性别不为男的学生信息。 USE PXSCJ GO SELECT * FROM XSB WHERE专业= '计算机' EXCEPTSELECT * FROM XSB WHERE性别=1执行结果如下:【例4.72】查找总学分大
查找总学分大于42且性别为男的学生信息。 SELECT * FROM XSB WHERE总学分>42 INTERSECTSELECT * FROM XSB WHERE性别=14.CTE在SELECT语句的最前面可以使用一条WITH子句来指定临时结果集,语法格式如下:[ WITH <common_table_expression> [ ,...n ] ]其中,<common_table_expression>::=expression_name[ ( column_name [ ,...n ] ) ]AS( CTE_query_definition )说明:expression_name是CTE的名称,column_name指定查询语句CTE_query_definition返回的数据字段名称,其个数要和CTE_query_definition返回的字段个数相同,若不定义,则直接命名查询语法的数据集合字段名称为返回数据的字段名称。
CTE下方的SELECT语句可以直接查询CTE中的数据。不允许在一个CTE中指定多个WITH子句。例如,如果CTE_query_definition包含一个子查询,则该子查询不能包括定义另一个CTE的嵌套的WITH子句。
【例4.73】使用
使用CTE从CJB表中查询选了101号课程的学生学号、成绩,并定义新的列名为number、point。再使用SELECT语句从CTE和XSB中查询姓名为“王林”的学生学号和成绩情况。 USE PXSCJ GO WITH cte_stu(number,point) AS (SELECT学号,成绩FROM CJB WHERE课程号='101') SELECT number, point FROM cte_stu, XSBWHERE XSB.姓名='王林' AND XSB.学号=cte_stu.n执行结果如下:定位点成员必须与UNION ALL、INTERSECT或EXCEPT结合使用。在最后一个定位点成员和第一个递归成员之间,以及组合多个递归成员时,只能使用UNION ALL运算符。递归CTE中所有成员的数据字段必须完全一致。递归成员的FROM子句只能引用一次递归CTE的名称。
在递归成员的CTE_query_definition中不允许出现下列项:
【例4.74】计算数字
计算数字1~10的阶乘。 WITH MyCTE(n,njc) AS(SELECT n=1, njc=1 UNION ALLSELECT n=n+1, njc=njc*(n+1) FROM MyCTEWHERE n<10) SELECT n, njc FROM MyCTE执行结果如下:
4.3.1视图概念视图一经定义以后,就可以像表一样被查询、修改、删除和更新。使用视图有下列优点:
1.在“SQL Server Management Studio”中创建视图其主要步骤如下。第1步:启动“SQL Server Management Studio”,在对象资源管理器中展开“数据库→PXSCJ”,选择其中的“视图”项,右击鼠标,在弹出的快捷菜单上选择“新建视图(N)”菜单项。
第2步:在随后出现的“添加表”窗口中,添加所需要关联的基本表、视图、函数、同义词。这里只使用“表”选项卡,选择表“XSB”,如图4.6所示,单击“添加”按钮。如果还需要添加其他表,则可以继续选择添加基表,如果不再需要添加,可以单击“关闭”按钮关闭该窗口。图4.6“添加表”快捷菜单
第3步:基表添加完后,在“视图”窗口的“关系图”窗口中显示了基表的全部列信息,如图4.7所示。根据需要在图4.7所示的窗口中选择创建视图所需的字段,可以在子窗口中的“列”一栏指定与视图关联的列,在“排序类型”一栏指定列的排序方式,在“筛选器”一栏指定创建视图的规则(本例在“专业”字段的“筛选器”栏中填写“计算机”)。图4.7创建视图
第4步:上一步完成后,单击面板上的“保存”按钮,出现“保存视图”对话框在其中输入视图名“CS_XS”,并单击“确定”按钮,便完成了视图的创建。视图创建成功后便包含了所选择的列数据。例如,若创建了CS_XS视图,则可查看其结构及内容。
查看的方法是:启动“SQL Server Management Studio”,在对象资源管理器中展开“数据库→PXSCJ→视图”,选择“dbo.CS_XS”,右击鼠标,在弹出的快捷菜单中选择“设计”菜单项,可以查看并修改视图结构,选择“编辑前200行”菜单项,将可查看视图数据内容。
2.使用CREATE VIEW语句创建视图T-SQL中用于创建视图的语句是CREATE VIEW语句,例如,用该语句创建视图CS_XS,其表示形式为USE PXSCJGOCREATE VIEW CS_XSASSELECT *FROM XSBWHERE专业= '计算机'语法格式:CREATE VIEW [ schema_name . ] view_name [ (column [ ,...n ] ) ][ WITH <view_attribute> [ ,...n ] ]AS select_statement [ ; ][ WITH CHECK OPTION ]
其中,<view_attribute> ::={[ ENCRYPTION ][ SCHEMABINDING ][ VIEW_METADATA ]}说明如下。
(4)select_statement:用来创建视图的SELECT语句,可在SELECT语句中查询多个表或视图,以表明新创建的视图所参照的表或视图。但对SELECT语句有以下限制:①定义视图的用户必须对所参照的表或视图有查询(即可执行SELECT语句)权限;②不能使用COMPUTE或COMPUTE BY子句;
③不能使用ORDER BY子句;④不能使用INTO子句;⑤不能在临时表或表变量上创建视图。(5)WITH CHECK OPTION:指出在视图上所进行的修改都要符合select_statement所指定的限制条件,这样可以确保数据修改后,仍可通过视图看到修改的数据。
例如对于CS_XS视图,只能修改除“专业”字段以外的字段值,而不能把“专业”字段的值改为“计算机”以外的值,以保证仍可通过CS_XS查询到修改后的数据。
【例4.75】创建CS_KC视图
创建CS_KC视图,包括计算机专业各学生的学号、其选修的课程号及成绩。要保证对该视图的修改都符合“专业为计算机”这一条件。 USE PXSCJ GO CREATE VIEW CS_KC WITH ENCRYPTIONASSELECT XSB.学号,课程号,成绩FROM XSB, CJBWHERE XSB.学号=CJB.学号AND专业= '计算机' WITH CHECK OPTION【例4.76】创建计算机专业学生
创建计算机专业学生的平均成绩视图CS_KC_AVG,包括学号(在视图中列名为num)和平均成绩(在视图中列名为score_avg)。 CREATE VIEW CS_KC_AVG(num,score_avg) ASSELECT学号, AVG(成绩) FROM CJBGROUP BY学号在一般情况下,如果视图为下列格式,则称其为分区视图。 CREATE VIEW view_name ASSELECT <select_list1> FROM T1 UNION ALLSELECT <select_list2> FROM T2 UNION ALL...SELECT <select_listn> FROM Tn【例4.77】使用视图
使用视图CS_KC查找计算机专业的学生学号和选修的课程号。SELECT学号,课程号FROM CS_KC【例4.78】查找平均成绩
查找平均成绩在80分以上的学生的学号和平均成绩。本例首先创建学生平均成绩视图XS_KC_AVG,包括学号(在视图中列名为num)和平均成绩(在视图中列名为score_avg)。 CREATE VIEW XS_KC_AVG ( num,score_avg ) ASSELECT学号, AVG(成绩) FROM CJBGROUP BY学号再对XS_KC_AVG视图进行查询。SELECT *FROM XS_KC_AVGWHERE score_avg >= 80执行结果如下:
例如,若限定某用户只能查询视图CS_XS,实际上就是限制了它只能访问XSB表的专业字段值为“计算机”的行。在创建视图时可以指定列,实际上也就是限制了用户只能访问这些列,从而视图也可看做数据库的安全措施。在使用视图查询时,若其关联的基本表中添加了新字段,则必须重新创建视图才能查询到新字段。
例如,若XSB表新增了“籍贯”字段,那么在其上创建的视图CS_XS若不重建视图,则查询SELECT * FROM CS_XS结果将不包含“籍贯”字段。只有重建CS_XS视图后再对它进行查询,结果才会包含“籍贯”字段。如果与视图相关联的表或视图被删除,则该视图将不能再使用。
1.可更新视图要通过视图更新基本表数据,必须保证视图是可更新视图。一个可更新视图可以是以下情形之一。
(3)通过INSTEAD OF触发器创建的可更新视图。INSTEAD OF触发器将在第7章介绍。例如,前面创建的视图CS_XS、CS_KC是可更新视图,而CS_KC_AVG是不可更新的视图。在对视图进行更新操作时,要注意基本表对数据的各种约束和规则要求。
2.插入数据使用INSERT语句通过视图向基本表插入数据,有关INSERT语句的语法介绍见第3章。
【例4.79】向CS_XS视图中插入
向CS_XS视图中插入以下记录:('081115', '刘明仪', 1, '1998-3-2', '计算机', 50 , NULL) INSERT INTO CS_XSVALUES('081115', '刘明仪', 1,'1998-3-2', '计算机',50,NULL)使用SELECT语句查询CS_XS依据的基本表XSB: SELECT * FROM XSB将会看到该表已添加了('081115', '刘明仪', 1,'1998-3-2', '计算机',50,NULL)行。当视图所依赖的基本表有多个时,不能向该视图插入数据,因为这将会影响多个基表。例如,不能向视图CS_KC插入数据,因为CS_KC依赖两个基本表:XSB和CJB。3.修改数据使用UPDATE语句可以通过视图修改基本表的数据。
【例4.80】将CS_XS视图中所
将CS_XS视图中所有学生的总学分增加8。 UPDATE CS_XSSET总学分=总学分+ 8该语句实际上是将CS_XS视图所依赖的基本表XSB中所有专业为“计算机”的记录的总学分字段值在原来基础上增加8。若一个视图依赖于多个基本表,则一次修改该视图只能变动一个基本表的数据。【例4.81】将CS_KC视图中学号
将CS_KC视图中学号为081101的学生的101号课程成绩改为90。 UPDATE CS_KCSET成绩=90WHERE学号='081101' AND课程号='101'本例中,视图CS_KC依赖于两个基本表:XSB和CJB,对CS_KC视图的一次修改只能改变学号(源于XSB表)或者课程号和成绩(源于CJB表)。 UPDATE CS_KCSET学号='081120',课程号='208'WHERE成绩=904.删除数据使用DELETE语句可以通过视图删除基本表的数据,不能使用DELETE语句。例如,不能通过对CS_KC视图执行DELETE语句而删除与之相关的基本表XSB及CJB表的数据。
【例4.82】删除CS_XS中女同学
删除CS_XS中女同学的记录。 DELETE FROM CS_XSWHERE性别= 0对视图的更新操作也可通过SQL Server Management Studio的界面进行,操作方法与对表数据的插入、修改和删除的界面操作方法基本相同,在此仅举一例加以说明。【例4.83】在对象资源管理器中对视图
在对象资源管理器中对视图CS_XS进行如下操作:(1)增加一条记录('081115', '刘明仪', 1, '1998-3-2', '计算机', 50 , NULL)。(2)将学号为081115的学生的总学分改为55。(3)删除学号为081115的学生记录。操作方法:(1)在对象资源管理器中展开“数据库→PXSCJ→视图”,选择“CS_XS”,右击鼠标,在弹出的快捷菜单上选择“编辑前200行”菜单项,在出现的如图4.8所示的数据窗口中添加新记录,输入新记录各字段的值。图4.8通过视图插入和删除数据
(2)定位到需修改的学号为“081115”的行的总学分字段,删除原值50,输入新值52。(3)定位到需删除的学号为“081115”的行,单击鼠标右键,在弹出的快捷菜单上选择“删除”,弹出“确认删除”对话框,在其中单击“是”按钮完成删除操作。
1.通过SQL Server Enterprise Manager修改视图在对象资源管理器中右击视图“dbo.CS_XS”,在弹出的快捷菜单中选择“设计”菜单项,进入视图修改窗口。该窗口与创建视图的窗口类似,其中可以查看并可修改视图结构,修改完后单击“保存图标”按钮即可。
2.使用ALTER VIEW语句修改视图语法格式:ALTER VIEW [ schema_name . ] view_name [ ( column [ ,...n ] ) ][ WITH <view_attribute> [ ,...n ] ]AS select_statement [ ; ][ WITH CHECK OPTION ]其中,view_attribute、select_statement等参数与CREATE VIEW语句中的含义相同。
【例4.84】将CS_XS视图
将CS_XS视图修改为只包含计算机专业学生的学号、姓名和总学分。 USE PXSCJ GO ALTER VIEW CS_XSASSELECT学号,姓名,总学分FROM XSBWHERE专业= '计算机'使用ENCRYPTION属性定义的视图可以使用ALTER VIEW语句修改。【例4.85】视图CS_KC
视图CS_KC是加密存储视图,修改其定义,包括学号、姓名、选修的课程号、课程名和成绩。 ALTER VIEW CS_KC WITH ENCRYPTIONASSELECT XSB.学号,XSB.姓名,CJB.课程号,KCB.课程名,成绩FROM XSB, CJB, KCBWHERE XSB.学号= CJB.学号AND CJB.课程号= KCB.课程号AND专业= '计算机' WITH CHECK OPTION1.通过对象资源管理器删除视图在对象资源管理器中删除视图的操作方法是:在“视图”目录下选择需要删除的视图,右击鼠标,在弹出的快捷菜单上选择“删除”菜单项,出现“删除”对话框,单击“确定”按钮,即删除了指定的视图。
2.T-SQL命令方式删除视图语法格式:DROP VIEW [ schema_name . ] view_name [ ...,n ] [ ; ]其中,view_name是视图名,使用DROP VIEW可删除一个或多个视图。例如,DROP VIEW CS_XS, CS_KC将删除视图CS_XS和CS_KC。
4.4.1游标概念一个对表进行操作的T-SQL语句通常都可产生或处理一组记录,但是许多应用程序,尤其是T-SQL嵌入到的主语言,通常不能把整个结果集作为一个单元来处理,这些应用程序就需要一种机制来保证每次处理结果集中的一行或几行,游标(cursor)就提供了这种机制。
SQL Server通过游标提供了对一个结果集进行逐行处理的能力,游标可看做一种特殊的指针,它与某个查询结果相联系,可以指向结果集的任意位置,以便对指定位置的数据进行处理。使用游标可以在查询数据的同时对数据进行处理。在SQL Server中,有两类游标可以用于应用程序中:前端(客户端)游标和后端(服务器端)游标。
服务器端游标是由数据库服务器创建和管理的游标,而客户端游标是由ODBC和DB-Library支持,在客户端实现的游标。SQL Server对游标的使用要遵循“声明游标→打开游标→读取数据→关闭游标→删除游标”的过程。
1.SQL-92语法语句格式:DECLARE cursor_name [ INSENSITIVE ] [ SCROLL ] CURSORFOR select_statement[ FOR { READ ONLY | UPDATE [ OF column_name [ ,...n ] ] } ][;]说明如下。
cursor_name:游标名,它是与某个查询结果集相联系的符号名,要符合SQLServer标识符命名规则。INSENSITIVE:指定系统将创建供所定义的游标使用的数据的临时复本,对游标的所有请求都从tempdb中的该临时表中得到应答。
SCROLL:说明所声明的游标可以前滚、后滚,可使用所有的提取选项(FIRST、LAST、PRIOR、NEXT、RELATIVE、ABSOLUTE)。select_statement:SELECT语句,由该查询产生与所声明的游标相关联的结果集。
该SELECT语句中不能出现COMPUTE、COMPUTE BY、INTO或FOR BROWSE关键字。READ ONLY:说明所声明的游标为只读的。UPDATE指定游标中可以更新的列,若有参数OF column_name [ ,…n ],则只能修改给出的这些列。
以下是一个符合SQL-92标准的游标声明:DECLARE XS_CUR1 CURSORFORSELECT学号,姓名,性别,出生时间,总学分FROM XSBWHERE专业= '计算机'FOR READ ONLY
2.T-SQL扩展语法格式:DECLARE cursor_name CURSOR[ LOCAL | GLOBAL ][ FORWORD_ONLY | SCROLL ][ STATIC | KEYSET | DYNAMIC | FAST_FORWARD ][ READ_ONLY | SCROLL_LOCKS | OPTIMISTIC ][ TYPE_WARNING ]FOR select_statement[ FOR UPDATE [ OF column_name [ ,…n ] ] ][;]以下是一个T-SQL扩展游标声明:DECLARE XS_CUR2 CURSORDYNAMICFORSELECT学号,姓名,总学分FROM XSBWHERE专业= '计算机'FOR UPDATE OF总学分
声明游标后,要使用游标从中提取数据,就必须先打开游标。在T-SQL中,使用OPEN语句打开游标,其格式为OPEN { { [ GLOBAL ] cursor_name } | cursor_variable_name }其中,cursor_name是要打开的游标名,cursor_variable_name是游标变量名,该名称引用一个游标。
GLOBAL说明打开的是全局游标,否则打开局部游标。OPEN语句打开游标,然后通过执行在DECLARE CURSOR(或SET cursor_variable)语句中指定的T-SQL语句来填充游标(即生成与游标相关联的结果集)。例如,语句OPEN XS_CUR1打开游标XS_CUR1。该游标被打开后,就可以提取其中的数据。
打开游标后,可以使用全局变量@@CURSOR_ROWS查看游标中数据行的数目。全局变量@@CURSOR_ROWS中保存着最后打开的游标中的数据行数。当其值为0时,表示没有游标打开;当其值为1时,表示游标为动态的;当其值为m(m为正整数)时,游标采用异步方式填充,m为当前键集中已填充的行数;
当其值为m(m为正整数)时,游标已被完全填充,m是游标中的数据行数。
【例4.86】定义游标
定义游标XS_CUR3,然后打开该游标,输出其行数。 DECLARE XS_CUR3 CURSORLOCAL SCROLL SCROLL_LOCKSFORSELECT学号,姓名,总学分FROM XSBFOR UPDATE OF总学分OPEN XS_CUR3 SELECT '游标XS_CUR3数据行数' = @@CURSOR_ROWS游标打开后,就可以使用FETCH语句从中读取数据了。
语法格式:FETCH[ [ NEXT | PRIOR | FIRST | LAST | ABSOLUTE { n | @nvar } | RELATIVE { n | @nvar} ]FROM ]{ { [ GLOBAL ] cursor_name } | @cursor_variable_name }[ INTO @variable_name [ ,…n ] ]
【例4.87】从游标
从游标XS_CUR1中提取数据。设该游标已经声明并打开。 FETCH NEXT FROM XS_CUR1执行结果如下:【例4.88】从游标
从游标XS_CUR2中提取数据。设该游标已经声明。 OPEN XS_CUR2 FETCH FIRST FROM XS_CUR2读取游标第一行(当前行为第一行),结果如下: FETCH NEXT FROM XS_CUR2读取下一行(当前行为第二行),结果如下:FETCH PRIOR FROM XS_CUR2读取上一行(当前行为第一行),结果如下:FETCH LAST FROM XS_CUR2读取最后一行(当前行为最后一行),结果如下:
FETCH RELATIVE-2 FROM XS_CUR2读取当前行的上两行(当前行为倒数第三行),结果如下:FETCH语句的执行状态保存在全局变量@@FETCH_STATUS中,其值为0表示上一个FETCH执行成功;为-1表示所要读取的行不在结果集中;为2表示被提取的行已不存在(已被删除)。
例如,接着上例继续执行如下语句:FETCH RELATIVE 3 FROM XS_CUR2SELECT 'FETCH执行情况' = @@FETCH_STATUS执行结果如下:
游标使用完以后要及时关闭。关闭游标使用CLOSE语句,格式为CLOSE { { [ GLOBAL ] cursor_name } | @cursor_variable_name }语句参数的含义与OPEN语句中的相同。例如,CLOSE XS_CUR2将关闭游标XS_CUR2。
游标关闭后,其定义仍在,需要时可用OPEN语句打开它再使用。若确认游标不再需要,就要释放其定义占用的系统空间,即删除游标。
删除游标使用DEALLOCATE语句,格式为DEALLOCATE { { [ GLOBAL ] cursor_name } | @cursor_variable_name }语句参数的含义与OPEN和CLOSE语句中的相同。例如,DEALLOCATE XS_CUR2将删除游标XS_CUR2。
下载地址:{{downurl}}
{{{a}}}
{{#b}}{{{b}}}
{{/b}} {{/title}} {{#nolog}}登陆注册
{{/nolog}} {{#djsx}}点我刷新
{{/djsx}} {{#gocz}} {{/gocz}} {{#ffqr}} {{/ffqr}}