insert into 变量语句中values中能引用变量,用了+或者&还是不行是怎么回事?

为什么php在向mysql提交数据时变量外要用单引号? - 知乎16被浏览<strong class="NumberBoard-itemValue" title="分享邀请回答$s='ss';
mysql_query("
INSERT INTO Comment (comment, date,
username, signature)
VALUES ('$s',
NOW(), '111',
$signature)
对SQL语句中 '$s' 的解释:因为$s变量对应comment字段,而该字段的类型是字符串.在SQL语法中,字符串赋值,就应该用单引号或双引号括起来.又因为PHP中整个SQL语句使用了双引号,所以里面的变量$s会被解析.题外话:PHP7已经不支持mysql扩展,建议使用mysqli或者pdo扩展.防御SQL注入应该使用预处理参数化查询,比如:$db = new mysqli($host, $user, $pass, $name, $port);
$db-&set_charset('utf8'); // 指定编码(重要)
INSERT INTO `comment` (comment, date, username, signature)
VALUES (?, ?, ?, ?)
$stmt = $db-&prepare($sql); // 预处理
$stmt-&bind_param('ssss', $var1, $var2, $var3, $var4); // 参数化
$stmt-&execute(); // 查询
var_export(
($stmt-&affected_rows === -1 || $stmt-&affected_rows === 0) ? false : $stmt-&insert_id
); // INSERT操作结果
81 条评论分享收藏感谢收起1添加评论分享收藏感谢收起博客访问: 138842
博文数量: 91
注册时间:
分类: Linux操作系统 17:29:26
绑定变量的变迁和使用像 select * from test where ch1=1;&&----1 是常量无论是 存储过程(PL/SQL)还是 一般的 语句在 9i 中,都会变成 select * from test where ch1='SYS_...'&&--系统自动生成一个变量但是在10g 中,还是保持原来的语句好了,现在说说绑定变量在 普通的sql语句或者动态的sql 语句(存储过程中定义)中,要显示指定使用绑定变了,否则,会变成 常量Sql*plus 中使用绑定变量:sql>sql> exec :x := 123;sql> SELECT fname, lname, pcode FROM cust WHERE id =:x;在过程中 的 动态sql语句中FOR i IN 1 .. 10 LOOP& && &&&OPEN l_rc FOR 'select object_name from test_b where object_id = :x' USING& && &&&FETCH l_rc INTO l_& && &&&CLOSE l_& && &&&END LOOP;如果单单是这么定义:FOR i IN 1..10 LOOP& && && & OPEN l_rc FOR 'select object_name from test_b where object_id = '||i;& && && & FETCH l_rc INTO l_& && && & CLOSE l_& && && & END LOOP;那么就不会使用到绑定变量,所以这也是要注意的地方还有,在非 动态sql 的pl/sql 块中,一般的引用变量就可以使用到绑定变量,所以我们也不必去专门做转化FOR i IN 1 .. 10 LOOP& & INSERT INTO test_a VALUES(i);&&END LOOP;&&FOR i IN 1 .. 10 LOOP& & INSERT INTO test_a SELECT i FROM&&END LOOP;像上面的 在过程中定义的语句,都可以使用到绑定变量;另外,绑定变量,在 视图中会变成 INSERT INTO TEST_A SELECT :B1 FROM DUAL&&这种形式,所以,基本上,只要在视图中一看到 有使用到 :B1 这种类型的东西,基本上可以认定为使用了绑定变量再有,在我的机器里面,trace文件中看到的语句都会变成 大写(即使原语句都是小写),但是其他的机子还没发现这种情况,不知道为什么
阅读(340) | 评论(0) | 转发(0) |
相关热门文章
给主人留下些什么吧!~~
请登录后评论。> 问题详情
INSERT语句中所使用的数据不能来自于______。A.数组B.变量C.查询D.索引
悬赏:0&答案豆
提问人:匿名网友
发布时间:
INSERT语句中所使用的数据不能来自于______。A.数组B.变量C.查询D.索引请帮忙给出正确答案和分析,谢谢!
为您推荐的考试题库
您可能感兴趣的试题
1在使用命令“INSERT INTO<表名>[(列名…)]VALUSE(<值>)”时,下列叙述中,错误的是______。A.INSERT语句中列名的顺序可以与表定义时的列名顺序一致B.INSERT语句中列名的顺序可以与表定义时的列名顺序不一致C.INSERT语句中值的顺序可以与列名的顺序不一致D.INSERT语句中值的顺序必须与列名的顺序一致2列出工资表中基本工资在1200元~1800元之间的职工信息,应使用的SQL查询语句是______。A.SELECT*FROM工资WHERE基本工资>=1200 OR基本工资<=1800B.SELECT*FROM工资WHERE基本工资IN()C.SELECT*FROM工资WHERE基本工资BETWEEN 1200 AND 1800D.SELECT*FROM工资WHERE基本工资LIKE()3建立一个“职员”表,表中有5个字段:职员号、姓名、性别、年龄、部门。要求职员号属性的值惟一,并且不能为空值。建立该表的SQL语句可以是______。A.CREATE TABLE职员(职员号CHAR(6),姓名CHAR(8),;性别CHAR(2),年龄INT(4),部门CHAR(12))B.CREATE TABLE职员(职员号C1LAR(6) NULL,姓名 CHAR(8),;性别CHAR(2),年龄INT(4),部门CHAR((12))C.CREATE TABLE职员(职员号CHAR(6) NOT NULL UNIQUE,;姓名CHAR(8),性别CHAR(2),年龄INT(4),部门CHAR(12))D.CREATE TABLE职员(职员号CHAR(6)UNIQUE,姓名CHAR(8),;性别CHAR(2),年龄INT(4),部门CHARR(12))4在学生表STUD中查询所有姓张的学生的信息,使用的SQL语句是______。A.SELECT*FROM STUD WHERE 姓名 LIKE"张%”B.SELECT*FROM STUD WHERE 姓名 IN("张%")C.SELECT*FROM STUD WHERE 姓名 LIKE"张$"D.SELECT*FROM STUD WHERE 姓名 IN"张$)"
我有更好的答案
请先输入下方的验证码查看最佳答案
图形验证:
验证码提交中……
每天只需0.4元
选择支付方式
支付宝付款
郑重提醒:支付后,系统自动为您完成注册
请使用微信扫码支付(元)
支付后,系统自动为您完成注册
遇到问题请联系在线客服QQ:
恭喜你被选中为
扫一扫-免费查看答案!
请您不要关闭此页面,支付完成后点击支付完成按钮
遇到问题请联系在线客服QQ:
恭喜您!升级VIP会员成功
提示:请截图保存您的账号信息,以方便日后登录使用。
常用邮箱:
用于找回密码
确认密码:请问insert语句中的Values能否带Select语句(有示例)?
[问题点数:40分,结帖人Dic4000]
请问insert语句中的Values能否带Select语句(有示例)?
[问题点数:40分,结帖人Dic4000]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
2010年4月 荣获微软MVP称号
2008年10月 MS-SQL Server大版内专家分月排行榜第二2008年6月 MS-SQL Server大版内专家分月排行榜第二
2010年8月 MS-SQL Server大版内专家分月排行榜第三
2010年8月 MS-SQL Server大版内专家分月排行榜第三
2010年8月 MS-SQL Server大版内专家分月排行榜第三
匿名用户不能发表回复!|当前位置: >>
数据库技术与应用―SQL Server 2008(第2版)第7章 操纵数据表中的数据
第7章操纵数据表中的数据1 主要内容? ? ? ? ? ? ? ? ? ? ? ?7.1 概述 7.2 数据操作 7.3 检索数据概述 7.4 使用select子句进行简单查询 7.5 使用where子句选择数据 7.6 聚合函数 7.7 分组查询 7.8 排序 7.9 连接查询 7.10 子查询技术 7.11 集合运算 本章小结2 7.1 概述表创建以后,往往只是一个没有数据的空表。因此,向表 中输入数据可能是创建表之后首先要执行的操作。无论表 中是否有数据,都可以根据需要向表中添加数据。当表中 的数据不合适或者出现了错误时,可以更新表中的数据。 如果表中的数据不再需要了,则可以删除这些数据。 ? 打开SQL Server Management Studio,选中需要更新数据 的表,如student,单击右键,选择“编辑前200行”,可 以打开student表,查看并修改表数据,如图7.1所示。该 窗口显示了表中已经存储的数据,数据列表的最后有一个 空行。插入数据时,将光标定位在空白行某个字段的编辑 框中,就可以输入新数据。编辑完成后,单击其他某一行, 即可提交新数据。?3 7.2 数据操作? ? ?7.2.1 用INSERT语句插入数据7.2.2 用UPDATE语句更新数据7.2.3 用DELETE语句删除数据4 7.2.1 用INSERT语句插入数据?INSERT语句的基本格式:INSERT [ INTO ] table_or_view_name [ ( column_list ) ] { { VALUES ( ( { DEFAULT | NULL | expression } [ ,...n ] ) [ ,...n ] ) | derived_table | DEFAULT VALUES } }5 各参数含义如下:? ?table_or view_name:要接收数据的表或视图的名称; ( column_list ) :要在其中插入数据的一列或多列的列 表。必须用括号将 column_list 括起来,并且用逗号进行 分隔。如果某列不在 column_list 中,则SQL SERVER必须能够基于该列提供一个值;否则不能加载行。如果列满足 下面的条件,则SQL SERVER将自动为列提供值: ? 具有 IDENTITY 属性。使用下一个增量标识值。 ? 有默认值。使用列的默认值。 ? 具有 timestamp 数据类型。使用当前的时间戳值。 ? 可为 NULL值。使用 NULL 值。 ? 是计算列。使用计算值。6 VALUES:引入要插入的数据值的列表。对于 column_list (如果已指定)或表中的每个列,都必须有一个数据值。 并且必须用圆括号将值列表括起来。 ? DEFAULT:强制数据库引擎加载为列定义的默认值。如果某 列并不存在默认值,并且该列允许NULL值,则插入 NULL。 ? derived_table:任何有效的 SELECT 语句,它返回将加载 到表中的数据行。 ? DEFAULT VALUES:强制新行包含为每个列定义的默认值。?7 (1)插入所有列数据??【例7.1】在Student表中插入一条新的学生信息。 INSERT INTO Student VALUES (&#39;8&#39;,&#39;曾玉林&#39;, &#39;男&#39;, &#39;&#39;, &#39;计算 机&#39;,20,NULL,&#39;;,NULL) 注意: ? 向表中插入数据时,数字数据可以直接插入,但是字符 数据和日期数据要用英文单引号引起来,不然就会提示 系统错误。 ? 当VALUES子句中数据值个数和顺序与表中定义的列的个 数和顺序完全一致时,( column_list )可以省略。否 则,不能省略。8 (2)插入部分列??【例7.2】在Student表中插入一条新的学生信息:学号为9, 姓名李林,性别为男,院系为计算机,周学时为18。 执行下面语句: INSERT INTO Student (studentID, studentName , sex, speciality, credithour) VALUES (&#39;9&#39;,&#39;李林&#39;, &#39;男&#39;, &#39;计算机&#39;,18) 注意,该语句不能写成: INSERT INTO Student VALUES (&#39;9&#39;,&#39;李林&#39;, &#39;男&#39;, &#39;计算机&#39;,18) 因为值列表的值个数与表中列的个数不一致9 (3)插入多行数据???使用INSERT [ INTO ] …… derived_table 命令可以一次 插入多行数据。 derived_table 可以是任何有效的 SELECT 语句。 【例7.3】将学生基本信息(学号、姓名、性别)插入到学 生名册表stu_Info中。 INSERT INTO stu_Info SELECT studentID,studentName,sex FROM student 使用INSERT……INTO形式插入多行数据时,需要注意下面 两点: ? 要插入的数据表必须已经存在; ? 要插入数据的表结构必须和SELECT语句的结果集兼容, 也就是说,二者的列的数量和顺序必须相同、列的数据 类型必须兼容等。10 (4)插入标识列数据???标识列的值由系统自动计算并保存在相应的记录中,因此 不能手工插入。在使用INSERT命令向包含有标识列的表插 入数据时,可直接忽略标识列。 【例7.4】将一条学生信息插入到表StuInfo中(表结构参 考6.4.1节表6.2)。 INSERT INTO StuInfo VALUES (&#39;张羽&#39;,&#39;女&#39;) 表StuInfo中有3列,第一列学号为标识列,插入数据时忽 略不计,该列的值由系统自动生成。11 ??那么标识列的数据是不是永远都没有办法手工更新呢?不 是的。如果想手工更新学号的值,可以通过以下方法实现。 ? 首先,使用SET命令打开INSERT_IDENTIYT选项: SET IDENTITY_INSERT student ON ? 然后使用INSERT命令插入数据。此时一定要显式指出更 新哪些列数据,包括标识列,即列列表不能省略。命令 如下: INSERT INTO StuInfo (stuID, stuName,sex) VALUES (3,&#39;汪华&#39;,&#39;男&#39;) 注意:INSERT_IDENTIYT选项为ON时,系统将不再自动为标 识列填入 值 。 如果 想恢复自 动输入 , 需要再次 执行 SET IDENTITY_INSERT student OFF,将IDENTITY_ INSERT选项 设置为OFF。12 7.2.2 用UPDATE语句更新数据???可以使用UPDATE语句更新表中已经存在的数据,该语句既可以一次更 新一行数据,也可以一次更新多行数据。 UPDATE语句的基本语法如下: UPDATE [ TOP ( n) [ PERCENT ] ] table_or_view_name SET { column_name = { expression | DEFAULT | NULL } | @variable = column { += | -= | *= | /= | %= | &= | ^= | |= } expression } [ WHERE &search_condition& ] 参数说明: ? TOP (n ) [ PERCENT ]:指定将要更新的行数或行百分比; ? table_or view_name:要更新行的表或视图的名称; ? SET:指定要更新的列或变量名称的列表 ? WHERE:指定条件来限定所更新的行。 ? &search_condition&:为要更新的行指定需满足的条件。13 ??当执行UPDATE语句时,如果使用了WHERE子句,则指定表中 所有满足WHERE子句条件的行都将被更新,如果没有指定 WHERE子句,则表中所有的行都将被更新。 【例7.5】将学生表Student中“李林”所属的学院由“计 算机”改为“数学”。UPDATE Student SET speciality = &#39;数学&#39; WHERE studentName = &#39;李林‘? ?更新数据时,每个列既可以被直接赋值,也可以通过计算 得到新值。 【例7.6】将所有计算机系学生的选课成绩加5分。UPDATE Grade SET grade =grade+5 WHERE studentID IN ( SELECT studentID FROM student WHERE speciality=&#39;计算机&#39;)14 7.2.3 用DELETE语句删除数据??当表中的数据不再需要的时候,可以将其删除。一般情况 下,可以使用DELETE语句删除表中的数据。该语句可以从 一个表中删除一行或多行数据。 使用DELETE语句删除数据的基本语法形式如下: ? DELETE [FROM] table_name ? [ WHERE search_condition ] ? 在DELETE语句中,如果使用了WHERE子句,表示从指定 的表中删除满足WHERE子句条件的数据行。如果没有使 用WHERE子句,则表示删除指定表中的全部数据。15 ??【例7.7】删除student表中姓名为“李林”的数据记录。 DELETE FROM student WHERE studentName = &#39;李林&#39; 如果想删除Exam表中的所有数据,直接执行: DELETE FROM Exam 或者 DELETE Exam。16 ??在删除表中的全部数据时,还可以使用TRUNCATE TABLE语 句,其格式为: ? TRUNCATE TABLE table_name TRUNCATE TABLE语句和DELETE语句都可以将表中的数据全 部删除,但是,两条语句又有不同的特点。 ? 一般情况下,当使用DELETE语句删除数据时,被删除的 数据记录在日志中。 ? 而当使用TRUNCATE TABLE语句删除数据时,系统将立即 释放表中数据和索引所占的空间,并且这种数据变化不 被记录在日志中。17 7.3 检索数据概述? ? ?检索数据是使用数据库的最基本的方式,也是最重要的方 式。 在SQL Server中,可以使用SELECT语句执行数据检索的操 作,查看表中的数据。 该语句具有非常灵活的使用方式和丰富的功能,它既可以 在单表上完成简单的数据查询,也可以在多表上完成复杂 的连接查询和嵌套查询。18 ??SELECT 语句的完整语法较复杂,其主要子句可归纳如下: ? SELECT select_list [ INTO new_table ] ? [ FROM table_source ] ? [ WHERE search_condition ] ? [ GROUP BY group_by_expression] ? [ HAVING search_condition] ? [ ORDER BY order_expression [ ASC | DESC ] ] 其中,SELECT子句指定将要查询的列名称,INTO子句用于 将查询得到的结果集插入并保存到一个新表中,FROM子句 指定将要查询的对象(表或视图),WHERE子句指定数据应 该满足的条件。19 ??? ?一般情况下,SELECT子句和FROM子句是必不可少的,WHERE 子句是可选的。如果没有使用WHERE子句,那么表示无条件 地查询所有的数据。 如果SELECT语句中有GROUP BY子句,则查询结果将按照分 组表达式的值进行分组,将该表达式的值相等的记录作为 一个组。如果GROUP BY句带有HAVING短语,则只有满足指 定条件的组才会输出。 如果有ORDER BY子句,则结果将按照排序表达式的值进行 升序或降序排列后再输出。 还可以在查询之间使用 UNION、EXCEPT 和 INTERSECT 运 算符,以便将各个查询的结果合并或比较到一个结果集中。20 7.4 使用select子句进行简单查询SELECT子句的select_list可以是表中的属性列,也可以是 表达式,或者说,可以是经过计算的值。可以在SELECT关 键字后面的列列表中使用各种运算符和函数。这些运算符 和函数包括算术运算符、数学函数、字符串函数、日期和 时间函数以及系统函数等。 ? 算术运算符(包括+、-、*、/ 和%)可以用在各种数值 列上,数值列的数据类型可以是INT、SMALLINT、TINYINT、 FLOAT、REAL、MONEY或SMALLMONEY。?21 ? ? ??【例7.8】查询当前SQL Server版本信息。 SELECT @@version 【例7.9】查询圆周率常数及其正弦、余弦值。 select PI(), SIN(PI()), COS(PI()) 在上述两个查询中,SELECT子句后分别使用了变量和函数, 从查询结果可以看到,在结果集中显示了“无列名”,可 以通过取别名的方法为这些列重新起名字。 定义别名有两种方法:一种是使用等号(=),一种是使 用AS关键字。 ? 使用等号时,其语法形式为:新标题=列名; ? 使用AS关键字时,其形式为:列名 [AS] 新标题,AS关 键字可以省略。22 ???以【例7.2】为例,可以通过下述语句给查询结果起别名: ? select PI() AS 圆周率常数,SIN(PI()) AS 圆周率 正弦值,COS(PI()) AS 圆周率余弦值; ? select圆周率常数=PI(),圆周率正弦值=SIN(PI()), 圆周率余弦值=COS(PI()); ? 两个语句执行结果完全一致。 在SELECT子句中还可以使用列名。因为列必须属于某个表, 所以此时需要从表中查询所需数据,需要同时使用FROM子 句。 【例7.10】查询全体学生的基本情况。 ? select * from student ? 该语句中使用“*”代表查询表中所有列。23 ? ?【例7.11】查询全体学生的学号、姓名及性别。 由题目可知,要查询的学号、姓名及性别是student表的几 个属性,此时只需要用列名指出想要查询的信息即可。select studentID,studentName,sex from student? ?还可以在SELECT子句中使用计算列(表达式)。 【例7.12】查询所有学生的姓名及其年龄。select studentName, year(getdate())-year(birthday) as age from student?该语句中使用了getdate()函数和year()函数,前者 用于获取系统当前日期,后者用于获取指定日期的年份。24 ? ?? ?【例7.13】查询选修了课程的学生学号。 分析学生一旦选课,其信息就会记录到成绩表Grade中,因 此查询选修了课程的学生学号就是查询在Grade表中有多少 个学生学号的问题。 SQL语句如下:select studentID from Grade从查询结果中可以看到,结果集中包含了许多重复的行。 这时因为默认地使用了ALL关键字。如果想去掉重复行,可 以指定DISTINCT关键字,SQL语句为:select distinct studentID from Grade25 7.5 使用where子句选择数据? ? ?7.5.1 确定查询 7.5.2 模糊查询 7.5.3 带查找范围的查询26 7.5.1 确定查询在WHERE子句中,确定查询指的是使用比较运算符、列表、 合并以及取反等运算方式进行的条件查询。 ? 比较运算符是搜索条件中最常用的。用于比较大小的运算 符一般包括:=(等于),&(大于),&(小于),&=(大 于等于),&=(小于等于),!=或&&(不等于)。 ? 【例7.14】查询所有计算机学院的学生学号和姓名。 ? 分析:student表中保存了所有学生信息,要想查询“计算 机”学院的学生信息,则学生记录需要满足院系为“计算 机”这一条件,亦即:speciality=“计算机”。?SELECT studentID, studentName FROM Student WHERE speciality = &#39;计算机&#39;27 ?【例7.15】查询Student表中所有年龄大于19岁的学生信息。 ? 分析:首先在Student表不存在“年龄”列,但是存在 “出生年月”列,因此年龄可以通过出生年月计算出来, 即:当前年份-出生年份=年龄。查询语句如下:SELECT * FROM Student WHERE year(getdate())-year(birthday)& 19??其 中 , WHERE 子 句 中 的 getdate() 和 year() 均 为 SQL SERVER提供的日期函数,分别用于获取系统日期和指定 日期的年份,其具体含义及使用方法请参看本书第8章 相关介绍。 该查询语句等价于:SELECT * FROM Student WHERE NOT year(getdate())-year(birthday)&=1928 ? ?? ?在WHERE子句中,还可以使用逻辑运算符(AND、OR和NOT) 把若干个查询条件合并起来,组成较复杂的查询条件。 AND运算符表示只有在所有的条件都为真时,才返回真。OR 运算符表示只要有一个条件为真,就可以返回真。NOT运算 符取反。当一个WHERE子句同时包含多个逻辑运算符时,其 优先级从高到低一次为NOT、AND、OR。用户也可以用括号改 变优先级。 【例7.16】查询Student表中所有男生或者年龄大于19岁的 学生姓名和年龄。 分析:查询的信息只需要满足“男生”“年龄大于19岁”两 个条件中的一个即可,可以使用OR来表示。SELECT studentName ,YEAR(getdate())-YEAR(birthday) as age FROM Student WHERE sex = &#39;男&#39; OR YEAR(getdate())-YEAR(birthday) & 1929 ? ?【例7.17】查询Grade表中成绩为空的学生学号。 分析:成绩为空亦即没有成绩,或成绩未定,而不是成绩 为0或成绩填入了空值(如空字符串)。在SQL语言里,使 用NULL关键字来表示未知、不确定或没有。SELECT studentID FROM Grade WHERE grade IS NULL?注意: ? 查询值是否为空,要使用关键字IS NULL,否定形式 为IS NOT NULL。 ? 一定不能使用“= NULL”或者“=&#39;&#39;”30 7.5.2 模糊查询?? ??通常在查询字符数据时,提供的查询条件并不是十分准确,例如,查 询仅仅是包含或类似某种样式的字符。这种查询称为模糊查询,在 WHERE子句中,可以使用LIKE关键字实现这种灵活的查询。 LIKE关键字用于搜索与特定字符串匹配的字符数据。LIKE关键字后面 可以跟一个列值的一部分而不是完整的列值。 其基本语法形式为: match_expression [ NOT ] LIKE pattern [ ESCAPE escape_character ] 参数说明: ? match_expression:任何有效的字符数据类型的表达式。 ? pattern:要在 match_expression 中搜索并且可以包括下列有效 通配符(表7.1)的特定字符串。 ? escape_character:放在通配符之前用于指示通配符应当解释为常 规字符而不是通配符的字符。31 表7.1LIKE子句中的通配符通配符 % _ [] [^] 代表任意单个字符含 义 包含零个或多个字符的任意字符串。指定范围或集合中的任意单个字符 不属于指定范围或集合中的任意单个字符32 ?需要强调的是,带有通配符的字符串必须使用单引号引起 来。下面是一些带有通配符的示例:? ? ?????LIKE &#39;AB%&#39; 返回以“AB”开始的任意字符串。 LIKE &#39;%ABC&#39; 返回以“ABC”结束的任意字符串。 LIKE &#39;[%]ABC%&#39; 返回以“%ABC”开始的任意字符串。 LIKE &#39;_AB&#39; 返回以“AB”结束的3个字符的字符串。 LIKE &#39;[ACE]%&#39; 返回以“A”、“C”、“E”开始的任意字符 串。 LIKE &#39;[A-Z]ing&#39; 返回4个字符长的字符串,结尾是“ing”, 第1个字符的范围是从A到Z。 LIKE &#39;L[^a]%&#39; 返回以“L”开始、第2个字符不是“a”的 任意字符串。?下面通过例子来说明LIKE子句的使用。33 ? ?【例7.18】查询所有姓王的学生的姓名、学号和性别。 分析:姓“王”的学生,其姓名必须满足这样的条件:姓 名第一个字为“王”,而剩下的部分可以是任意字,并且 可以是任意多个字。由此可见从第二个字开始应使用“%” 通配符:SELECT studentID,studentName ,sex FROM Student WHERE studentName LIKE &#39;王%&#39;? ?【例7.19】查询所有不姓刘的学生姓名和学号。 分析:所有不姓刘的学生信息没有办法直接查询出来,但 是可以直接查询出所有姓刘的学生信息:SELECT studentID,studentName ,sex FROM Student WHERE studentName LIKE &#39;刘%&#39;34 ?再对这些信息取否定,即NOT LIKE,就可以得到所有不姓刘的学生信 息。代码如下:SELECT studentID,studentName ,sex FROM Student WHERE studentName NOT LIKE &#39;王%&#39;【例7.20】查询姓名中第二个字为“敏”字的教师信息。 ? 分析:姓名中第二个字为“敏”,显然“敏”字前面必须 有且只能有一个字,所以要用到通配符“_”,而“敏”字 后面可以有字也没有没有字,是任意长度的字符串,要用 到通配符“%”。SQL语句如下:?SELECT * FROM Teacher WHERE teacherName LIKE &#39;_敏%&#39;35 ??可以将通配符模式匹配字符作为文字字符使用。若要将通 配符作为文字字符使用,请将通配符放在方括号中。如字 符串“[%]ABC%”,表示以“%ABC”开始的任意字符串。 如果用户要查询的字符串本身就含有通配符,这时就要使 用ESCAPE关键字,对通配符进行转义。36 ? ??【例7.21】查询DB_Design课程的课程号和学分。 分析:在课程名“DB_Design”中包含了符号“_”,如果直接 使用条件LIKE DB_Design查询,显然SQL会把条件中的“_” 作 为 通 配 符 处 理 , 那 么 得 到 的 结 果 就 是 “ 以 DB 开 头 以 Design结尾第三个字符可以是任意字符”的课程名,如 DBADesign。因此在该查询以及类似查询中,需要对通配符 字符进行“转义”,以便告诉SQL分析器,字符串中的哪些 符号是普通符号,不要作为通配符来处理。 转义的方法是使用ESCAPE子句,并在ESCAPE子句后跟上转 义字符,转义字符可自己定义。SELECT courseID, credithour FROM Course WHERE courseName LIKE &#39;DB\_Design&#39; ESCAPE &#39;\&#39;?ESCAPE &#39;\&#39;表示“\”为转义字符,这样匹配字符串中紧跟 在“\”后面的字符“_”就不再具有通配符的含义,而是转义 为普通的“_”字符处理。37 7.5.3 带查找范围的查询??谓词IN、NOT IN和BETWEEN…AND…、NOT BETWEEN…AND…可以用来查 找属性值在或不在指定范围内的元组。其中,BETWEEN后是范围的下限, AND后是范围的上限。 【例7.22】查询年龄在19~22之间的学生的姓名、年龄和所属院系。 SELECT studentName,YEAR ( getdate() ) C YEAR ( birthday ), speciality FROM Student WHERE YEAR(getdate())-YEAR(birthday) BETWEEN 19 AND 22 ? 此查询等价于: SELECT studentName, YEAR ( getdate() ) C YEAR ( birthday), speciality FROM Student WHERE YEAR(getdate())-YEAR(birthday) IN (19,20,21,22)38 ? ? ??与BETWEEN…AND…相对的谓词是NOT BETWEEN…AND…。 【例7.23】查询所属院系为计算机或者化学系的学生信息。 分析:可以把所有学生所属院系看作一个集合,而每个学 生所属的院系就是集合中的一个。匹配集合中的某个值可 以使用谓词IN。 代码如下:SELECT *FROM Student WHERE speciality in (&#39;计算机&#39;,&#39;化学&#39;)?该查询等价于:SELECT *FROM Student WHERE speciality = &#39;计算机&#39; or speciality = &#39;化学&#39;39 7.6 聚合函数在SELECT 语句中使用聚合函数,可为表中的值创建汇总。聚 合函数又称聚集函数、统计函数,它对一组值执行计算,并返 回单个值。在SQL SERVER中主要提供以下几类聚合函数: ? 计数: COUNT ( [ DISTINCT | ALL ] expression | * ) ? 计算总和: SUM ( [ DISTINCT | ALL ] expression ) ? 计算平均值: AVG ( [ DISTINCT | ALL ] expression ) ? 求最大值: MAX ( [ DISTINCT | ALL ] expression ) ? 求最小值: MIN ( [ DISTINCT | ALL ] expression )40 ?注意: ? 除了 COUNT 以外,聚合函数都会忽略空值(NULL); ? 聚合函数只能在以下位置作为表达式使用: ? SELECT 语句的选择列表(子查询或外部查询)。 ? HAVING 子句。41 ? ??【例7.24】查询学生总人数。 分析:首先确定要使用的函数,统计学生人数显然要使用 计数函数即COUNT函数。接下来确定COUNT计数时使用的参 数 。 学 生 信 息 保 存 在 student 表 中 , 学 生 总 人 数 等 价 于 student表中学生的记录个数或学号个数。因此统计总人数 实际上就是统计student表中的记录数或学号个数。 SQL语句如下:SELECT COUNT (*) FROM Student 或: SELECT COUNT (studentID) FROM Student42 ?【例7.25】查询选修了课程的学生人数。 ? 由于一个学生可能选择多门课程,所以在计算时要要避 免一个学生重复计数。所以可以使用DISTINCT关键字对 学生学号studentID进行筛选,保证同一个学号只计数 一次。 ? 代码如下:SELECT COUNT ( DISTINCT studentID) FROM Grade43 ? ???【例7.26】计算计算机系学生选修1号课程的平均成绩。 分析:显然,要计算平均成绩需要使用AVG函数对Grade表中的成绩列 grade运算。但是Grade表中保存了所有学生的1号课程成绩,我们需要 从中筛选出来计算机系的相关信息。“计算机”信息保存在student表 中,如何把这二者联系起来呢?可以通过两张表共有的属性 “studentID”来完成。 首先通过student 表找出所有“计算机”系学生的studentID,只要 Grade表中的studentID等于其中的某个值,就表明Grade表中的这项纪 录是“计算机”系学生的选课纪录。接着就可以进一步找出所有计算机 系选修1号课程的纪录,进而计算平均成绩。 参考SQL语句如下: SELECT AVG(Grade) FROM Grade WHERE courseID=&#39;1&#39; and studentID IN ( SELECT studentID from student where speciality=&#39;计算机&#39;)44 7.7 分组查询??使用分组技术可以将记录按属性分组,属性值相等的为一 组。这样做的目的是为了细化统计函数的作用对象,如果 未对查询结果分组,集函数将作用于整个查询结果;而对 查询结果分组后,集函数将分别作用于每个组。 分组的一般格式为: ? GROUP BY [ ALL] group_by_expression [ ,...n ]45 ?【例7.27】统计每个院系的学生总人数。 ? 要想统计每个院系的学生人数,需要先把院系一样的记 录放到一起作为一组,然后统计改组的人数,即:按院 系(speciality)分组,统计人数。 ? SQL语句如下: ? SELECT COUNT (*) ? FROM Student ? GROUP BY speciality46 ??【例7.28】查询每门课程的选课平均成绩及选课人数。 ? 分析:要想计算每门课程的平均成绩和选课人数,需要 把“课程号”相同的纪录(同一门课)作为一组来进行 运算。即按课程号courseID分组。 ? SQL语句如下: ? SELECT courseID, AVG(grade) AS 平 均 成 绩,COUNT(studentID) AS 选课人数 ? FROM Grade ? GROUP BY courseID 如果分组后还要求按一定的条件对这些组进行筛选,最终 只输出满足指定条件的组,则可以使用HAVING短语指定筛 选条件。47 ?【例7.29】查询选修了2门以上课程的学生学号。 ? 分析:先用GROUP BY子句按学号studentID进行分组, 再用统计函数COUNT对每一组计数。HAVING短语给出了 输出结果的条件,只有满足这个条件(即元组个数&2) 的组才会输出显示。 ? SQL语句如下: ? SELECT studentID FROM Grade ? GROUP BY studentID ? HAVING COUNT(*) &2 ? 该查询也可用以下代码实现: ? SELECT studentID FROM Grade X ? WHERE (SELECT COUNT(*) FROM Grade Y WHERE X.studentID=Y.studentID)&=2 ? GROUP BY studentID48 注?意??? ?GROUP BY子句的作用对象是查询的中间结果表,它按照指定 的一列或多列值进行分组,值相等的为一组。因此,使用 GROUP BY子句后,SELECT子句的列名列表中只能出现分组属 性和聚合函数。 例如,下面的语句就是不对的,因为courseID既不是分组属 性,也没有包含在聚合函数中。 ? SELECT studentID, courseID FROM Grade ? GROUP BY studentID ? HAVING COUNT(*) &2 因为HAVING子句是作为GROUP BY子句的条件出现的,所以 HAVING子句一般与GROUP BY子句同时出现,并在必须出现在 GROUP BY 子 句 之 后 。 如 果 不 使 用 GROUP BY 子 句 , 则 HAVING 的行为与 WHERE 子句一样。 GROUP BY子句可以包含表达式。 在HAVING子句中的列只返回一个值。49 ??【例7.30】查询课程成绩有2门(或以上)超过80分的学生 学号及相应(80分以上)的课程数。 ? 分析:先从Grade表中筛选出来所有80分以上的选课纪 录,然后再按学生(分组)统计选修课程的门数,超过 两门的学生信息即是所求。 ? SQL语句如下: ? SELECT studentID, COUNT(*) FROM Grade ? WHERE grade & 80 ? GROUP BY studentID ? HAVING COUNT(*) &=2 由此可见:HAVING短语与WHERE子句的区别在于作用对象不 同。WHERE子句作用于基表或视图,从中选择满足条件的元 组。HAVING短语作用于组,从中选择满足条件的组。50 7.8 排序??使用ORDER BY子句可以按一个或多个属性列对数据进行排 序。默认的排序方式有两种,升序和降序,分别使用关键 字ASC和DESC来指定。当排序列包含空值(NULL)时,空值 默认以最大值处理。 基本格式如下: ? ORDER BY order_by_expression [ ASC | DESC ] [ ,...n ] ? 其中,排序表达式可以是列名、表达式或者正整数。正 整数表示表中列的位置(第几列)。51 ?【例7.31】查询选修了2号课程的学生学号及其成绩,并按 分数降序输出结果。 ? SELECT studentID, grade FROM Grade ? WHERE courseID = &#39;2&#39; ? ORDER BY grade DESC52 当基于多个属性对数据进行排序时,出现在ORDER BY子句 中的列的顺序是非常重要的,因为系统是按照排序列的先 后进行排序的。如果第一个属性相同,则依据第二个属性 排序,如果第二个属性相同,则依据第三个属性排序,依 此类推。。 ? 【例7.32】查询全体学生信息,查询结果按学生所在系的 系名升序排列,同一个系中的学生按年龄降序排列。 ? SELECT * FROM Student ? ORDER BY speciality, birthday ? 在该查询中,系统先按照院系speciality升序进行排序 (关键字ASC省略),然后对于院系相同的元组再按照 出生年月降序(即年龄升序)进行排序。?53 当在查询语句中使用了ORDER BY子句时,还经常在SELECT 子句中使用TOP关键字。TOP关键字表示仅在结果集中从前 向后列出 指定数量 的数据行 。如果在 使用 TOP关 键字的 SELECT语句中没有使用排序子句,则只是随机地返回指定 数量的数据行。 ? 使用TOP关键字的基本语法有两种: ? TOP (n):从前向后返回n行数据 ? TOP (n) PERCENT:按照百分比返回指定数量的数据行?54 ?【例7.33】查询班内前5个学生的信息。 ? SELECT TOP (5) * ? FROM Student ? ORDER BY studentID ? 本查询先将结果集中的数据按照studentID升序排序, 然后取出前5个输出显示。55 【例7.34】查询程序设计基础课程成绩排名在前30%的学 生学号、姓名和成绩。 ? 分析:先筛选得到“程序设计基础”课程的选课信息并按 “成绩”降序排序,然后取出前面30%的记录输出显示。注 意:因此本查询涉及到的信息牵涉到了三张表,因此需要 将三张表联接起来进行查询,关于联接查询请参考7.9节。 ? 本查询SQL语句如下: ? SELECT TOP (30) PERCENT Grade.studentID, studentName, Grade ? FROM Grade JOIN Student ON Grade.studentID = Student.studentID JOIN Course ON Grade.courseID=Course.courseID ? WHERE coursename=&#39;程序设计基础&#39; ? ORDER BY Grade DESC?56 7.9 连接查询在设计表时,为了提高表的设计质量,经常把相关的数据 分散在不同的表中。但是,在实际使用时,往往需要同时 从两个或两个以上表中检索数据,并且每一个表中的数据 往往仍以单独的列出现在结果集中。实现从两个或两个以 上表中检索数据且结果集中出现的列来自于两个或两个以 上表中的检索操作称为连接技术。 ? 通过连接,可以从两个或多个表中根据各个表之间的逻辑 关系来检索数据。连接指明了 Microsoft SQL Server 应 如何使用一个表中的数据来选择另一个表中的行。 ? 连接查询是关系数据库中最主要的查询,包括交叉连接、 内部连接、外部连接三种。 ? 可 以 在 FROM 或 WHERE 子 句 中 指 定 内 连 接 ; 而 只 能 在 FROM 子句中指定外连接。连接条件与 WHERE 和 HAVING 搜索条件相结合,用于控制从 FROM 子句所引用的基表中 选定的行。?57 ???在FROM子句中指出连接时有助于将连接操作与WHERE子句中 的搜索条件区分开来。所以,在Transact-SQL中推荐使用 这种方法。 在FROM子句中指定连接条件的语法格式为: ? FROM first_table join_type second_table [ON (join_condition)] ? 其中: ? 连接类型join_type可以是交叉连接(CROSS JOIN)、 内部连接(INNER JOIN)、外部连接; ? ON子句指出连接条件,它由被连接表中的列和比较运 算符、逻辑运算符等构成。 连接可以对同一个表操作,也可以对多表操作,对同一个 表操作的连接又称做自连接;58 连接查询? ? ?7.9.1 交叉连接7.9.2 内连接 7.9.3 外连接59 7.9.1 交叉连接??交叉连接也称为笛卡儿乘积,它返回两个表中所有数据行 的全部组合,所得结果集中的数据行数等于第一个表中的 数据行数乘以第二个表中的数据行数。 交叉连接使用关键字CROSS JOIN来创建,并且不带WHERE 子句。例如,对Student表和Course表执行交叉连接,如图 7.33所示,由于Student表中有7行数据,Course表中有5行 数据,因此结果集中包含了35行数据。60 ? ??但是,如果添加了 WHERE 子句,则交叉连接的行为将与内 部连接行为相似。 例如:下面两段代码执行得到的结果集是一样的。 ? SELECT * FROM Student CROSS JOIN Course ? WHERE speciality =&#39;计算机&#39;; --带WHERE子句的外连接 ? SELECT * FROM Student INNER JOIN Course ? ON speciality =&#39;计算机&#39; ; --内连接 在实际的应用中,交叉连接的使用是比较少的,但是它是理 解外连接和内连接的基础。61 7.9.2 内连接? ? ?(1)等值连接查询 (2)不等值连接查询 (3)自连接查询62 (1)等值连接查询? ?连接条件或连接谓词中的运算符为等号的连接查询,称为等 值连接。 【例7.35】查询每个学生选修课程的情况。???学生信息存放在Student表中,学生选课信息存放在Grade表中,所 以本查询实际上涉及Student与Grade两个表。这两个表之间的联系 是通过公共属性studentID实现的。 法(一):在FROM子句中指定连接条件 ? SELECT * ? FROM student INNER JOIN Grade ? ON student.studentID = grade .studentID 法(二):在WHERE子句中指定连接条件 ? SELECT * ? FROM student , Grade ? WHERE student.studentID = grade .studentID63 ??本例中,SELECT子句、ON子句与WHERE子句中的属性名前都 加上了表名前缀,这是因为在Student表和Grade表中都有属 性studentID,为了避免混淆,必须加上表名。如果属性名 在参加连接的各表中是惟一的,则可以省略表名前缀。 SQL SERVER 2008执行该连接操作的一种可能过程是: ? 首先,在Student表中找到第一个元组,然后从头开始扫 描Grade表,逐一查找与Student第一个元组的StudentID 相等的Grade元组; ? 找到后就将Student中的第一个元组与该元组拼接起来, 形成结果表中的一个元组; ? Grade全部查找完后,再找Student中的第二个元组,然 后再从头开始扫描Grade表,逐一查找满足连接条件的元 组,找到后就将Student中的第二个元组与该元组拼接起 来,形成结果表中的一个元组。 ? 重复以上操作,直到Student表中的全部元组都处理完毕。64 (2)不等值连接查询?? ?当连接条件或连接谓词中的运算符不是等号(=)时,将该 连接称为不等值连接。这些运算符可以是:&、&=、&、 &=、!=(或&&),还可以使用BETWEEN…AND…之类的谓词。 一般情况下,不等值连接通常和等值连接一起组成复合条 件,共同完成一组查询。 【例7.36】查询每个学生选修课程成绩大于80′的情况。 ? 学生情况 存放在 Student 表中 ,学生选课情况存放在 Grade表中,所以本查询实际上涉及Student与Grade两 个表。这两个表之间的联系是通过公共属性studentID 实现的。 ? 法(一):在FROM子句中指定连接 ? SELECT Student.*, Grade.* ? FROM Student INNER JOIN Grade ? ON Student.studentID = Grade.studentID AND Grade.Grade &80 65 ??如果在进行等值或不等值连接时目标列不使用“*”而使用 列名称,从而把结果集中重复的属性列去掉,就成了自然 连接。 例如,在【例7.35】中, 查询每个学生选修课程的情况, 并去掉重复列。可以使用下面的SQL语句: ? SELECT Student.studentID, studentName, birthday, speciality, courseID, Grade ? FROM Student INNER JOIN Grade ? ON Student.studentID = Grade.studentID66 (3) 自连接查询连接不仅可以在不同的表之间进行,还可以在同一张表上 进行,这种连接称为自连接(Self Join),相应的查询称 为自连接查询。 ? 【例7.37】查找课程不同成绩相同的学生的学号、课程号 和成绩(不考虑同一学生成绩相同的情况)。 ? 要查询不同学生课程不同成绩相同的信息,显然,要使用 两张Grade表。在第一张表中保存学生的课程、成绩,在第 二张表中逐条读取学生成绩记录与第一张表中的记录比较, 看是否满足条件:课程不同、成绩相同。 ? SQL语句如下:???SELECT X.studentID,X.courseID ,X.grade ,Y.studentID , Y.courseID ,Y.grade FROM Grade X JOIN Grade Y ON X.courseID &&Y.courseID AND X.grade =Y.grade AND X.studentID &&Y.studentID67 ?分析查询结果,可以看到,结果集中的数据并不是我们最 终想要的,因为里面的记录两两重复了。在自连接查询中, 这是经常出现的情况,因为所有的记录都会被比较两次。 要想得到最终的结果,需要加上一些限制条件对结果进一 步处理。执行下面的语句,观察结果有什么变化。??SELECT X.studentID,X.courseID ,X.grade ,Y.studentID , Y.courseID ,Y.grade FROM Grade X JOIN Grade Y ON X.courseID &&Y.courseID AND X.grade =Y.grade AND X.studentID &Y.studentID?思考:如果需要把同一个学生不同课程、成绩相同的记录 同时显示出来,语句该如何实现?68 7.9.3 外连接在内连接操作中,只有满足连接条件的元组才能作为结果 输出,如在【例7.35】的结果表中没有关于5、6、7号学生 的选课信息,原因在于他们没有选课,在Grade表中没有这 些学生相应的记录,因此内连接后就没有这些学生的选课 信息。 ? 但是有时需要以Student表为主体列出每个学生的基本情况 及其选课情况,若某个学生没有选课,则只输出其基本情 况信息,其选课信息为空值即可,这时可以使用外连接 (OUTER JOIN)。 ? 在Microsoft SQL SERVER 2008系统中,可以使用3种外连 接关键字,即LEFT OUTER JOIN(或LEFT JOIN),RIGHT OUTER JOIN(或RIGHT JOIN)和FULL OUTER JOIN(或FULL JOIN)。?69 ? ? ?LEFT OUTER JOIN表示左外连接,结果集中将包含左表中的 所有数据和第二个连接表中满足条件的数据。 RIGHT OUTER JOIN表示右外连接,结果集中将包含右表中 的所有数据和第一个连接表中满足条件的数据。 FULL OUTER JOIN表示全外连接,它综合了左外连接和右外 连接的特点,返回两个表的所有行。对于不满足外连接条 件的数据在另外一个表中的对应值以NULL填充。70 ? ???【例7.38】查询所有学生选修课程的情况,包括没有选修课 程的学生。 本例和【例7.35】不同的地方在于,【例7.35】只需输出选 修了课程的学生信息,没有选修课程的学生信息不输出;而 本例却必须输出全部学生信息。因此,必须使用外连接才能 实现。 SQL语句如下: ? SELECT Student.studentID,Student.studentName, courseID, grade ? FROM Student LEFT OUTER JOIN Grade ? ON Student.studentID = Grade.studentID 在该查询语句中,使用了左外连接。所以Student表(左表) 中的数据将全部输出,而Grade表(右表)中不满足查询条 件的数据记录在对应的记录位置上都用NULL表示。 71 ?本例也可以用右外连接来完成。这时只需要把Student表和 Grade表的位置调换一下即可: ? SELECT Student.studentID,Student.studentName, courseID, grade ? FROM Grade RIGHT OUTER JOIN Student ? ON Student.studentID = Grade.studentID72 7.10 子查询技术??在SQL语言中,一个SELECT…FROM…WHERE…语句称为一个 查询块。将一个查询块嵌套在另一个查询块的WHERE子句或 HAVING短语的条件中的查询称为嵌套查询,又称为子查询。 例如: SELECT studentName FROM Student WHERE studentID IN ( SELECT studentID FROM Grade WHERE courseID = &#39;2&#39; ) ;73 ?? ?在本例中,下层查询块“SELECT studentID FROM Grade WHERE courseID = ?2?” 是 嵌 套 在 上 层 查 询 块 “ SELECT studentName FROM Student WHERE studentID IN”的WHERE 子句中的。 上层查询块称为外层查询或者父查询,下层查询块称为内 层查询或子查询。 当查询语句比较复杂、不容易理解,或者一个查询依赖于 另外一个查询结果时,就可以使用子查询。74 ? ? ? ? ?SQL语言允许多层嵌套查询,即一个子查询中还可以嵌套其 他子查询。在使用子查询时,需要注意以下几点: 子查询必须使用圆括号括起来。 子查询中不能使用ORDER BY子句。 如果父查询中使用了ORDER BY子句,则ORDER BY子句必须 与TOP子句同时出现。 嵌套查询一般的求解方法是由里向外,即每个子查询要在 上一级查询处理之前求解,子查询的结果用于建立其父查 询要使用的查找条件。75 ? ? ? ?7.10.1 带IN的嵌套查询7.10.2 带比较运算符的嵌套查询 7.10.3 带ANY或ALL的嵌套查询 7.10.4 带EXISTS的嵌套查询76 7.10.1 带IN的嵌套查询?? ?在嵌套查询中,子查询的结果往往是一个集合,所以谓词 IN是嵌套查询中最常使用的谓词。其主要使用方式为: ? WHERE expression [NOT] IN ( subquery ) 需要注意的是:包含IN和NOT IN的子查询只能返回一列数 据。 【例7.39】查询与“王恒”在同一个院系学习的学生信息。 ? 先分步完成此查询,然后再构造嵌套查询。 ? (1)确定“王恒”所在的系名。 SELECT speciality FROM Student WHERE studentName=&#39;王恒&#39; ? 查找结果为“计算机”。77 ??(2)查找所有在“计算机”系学习的学生信息。 SELECT * FROM Student WHERE speciality=&#39;计算机‘ 然后将第(1)步查询嵌入到第(2)步查询中,构造出 嵌套查询: SELECT * FROM Student WHERE speciality IN (SELECT speciality FROM Student WHERE studentName=&#39;王恒&#39;)78 ? ?【例7.40】查询选修了课程名为“数据库原理”的学生学号 和姓名。 分析:本查询涉及学号、姓名和课程名3个属性。学号和姓 名存放在Student表中,课程名存放在Course表中,这两个 表之间没有直接的联系,所以需要通过Grade表建立二者之 间的联系。因此本查询实际上涉及3个关系。SELECT studentID, studentName ③最后在Student表中取出相应学 FROM Student 号的学生信息 WHERE studentID IN ( SELECT studentID ②然后在Grade中找出选修了3号 FROM Grade 课程的学生学号为:1、2、4 WHERE courseID IN ( SELECT courseID ①首先在Course表中找出“数据库 FROM Course 原理”的课程号,结果为3 WHERE coursename= &#39;数据库原理&#39; ) )79 7.10.2?带比较运算符的嵌套查询?带有比较运算符的子查询是指父查询与子查询之间用比较 运算符进行连接。当用户能确切知道内层查询返回的是单 值时,可以用=、&、&、&=、&=、!=或&&等比较运算符。 例如,在【例7.39】中,由于一个学生只可能在一个系学 习,也就是说子查询的结果是一个值,因此可以用“=”代 替“IN”,其SQL语句如下: SELECT * FROM Student WHERE speciality = (SELECT speciality FROM Student WHERE studentName=&#39;王恒&#39;)80 【例7.39】和【例7.40】中的子查询都只执行一次,其查询 结果用于父查询。子查询的条件不依赖于父查询,这类子查 询称为不相关子查询。不相关子查询是较简单的一类子查询。 ? 如果子查询的查询条件依赖于父查询,这类子查询称为相关 子查询。下面就是一个相关子查询的例子。 ? 【例7.41】找出每个学生超过他选修课程平均成绩的课程号。 ? 分析:该查询需要用到两张表,一张是学生的选课成绩表 Grade,另一张是学生的平均成绩表,存放学生的平均成绩, 该表可以通过查询的结果集来构造。然后用第一张表的学生 成绩跟第二张表中该学生的平均成绩做比较,即可找出满足 条件的记录。?81 ??SQL语句如下: ? SELECT studentID, courseID ? FROM Grade x ? WHERE grade & = ( SELECT AVG (grade) FROM Grade y WHERE y.studentID = x.studentID ) x是表Grade的别名,又称为元组变量,可以用来表示Grade 的一个元组,内层查询是求一个学生所有选修课程平均成绩 的,至于是哪个学生的平均成绩要看参数x.studentID的值, 而该值是与父查询相关的,因此这类查询称为相关子查询。82 7.10.3 带ANY或ALL的嵌套查询?子查询返回单值时,可以用比较运算符,但返回多值时, 要用ANY或ALL谓词修饰符。而使用ANY或ALL谓词时,必须 同时使用比较运算符。其语义为:&ANY &ALL 大于子查询结果中的某个值 大于子查询结果中的所有值&ANY&ALL &=ANY &=ALL &=ANY &=ALL =ANY =ALL !=(或& &)ANY != (或& &)ALL小于子查询结果中的某个值小于子查询结果中的所有值 大于等于子查询结果中的某个值 大于等于子查询结果中的所有值 小于等于子查询结果中的某个值 小于等于子查询结果中的所有值 等于子查询结果中的某个值 等于子查询结果中的所有值(通常没有实际意义) 不等于子查询结果中的某个值 不等于子查询结果中的任何一个值83 ? ?【例7.42】查询其他系中比计算机系所有学生年龄都大的 学生姓名、年龄和所属院系。 SQL语句如下:SELECT studentName, birthday, speciality FROM Student WHERE year(getdate())-year(birthday) &ALL ( SELECT year(getdate())-year(birthday) FROM Student WHERE speciality = &#39;计算机&#39; ) AND speciality != &#39;计算机‘?系统执行此查询时,首先处理子查询,找出计算机系中所 有学生的年龄,构成一个集合(18,19,20,21)。然后处理 父查询,找出所有非计算机系且年龄大于21的学生。84 ??本查询也可以用聚合函数来实现。首先用子查询找出计算 机系学生的最大年龄(21),然后在父查询中查询所有非 计算机系其年龄大于21的学生。 SQL语句如下: SELECT studentName, birthday, speciality FROM Student WHERE birthday & ( SELECT MAX(birthday) FROM Student WHERE speciality = &#39;计算机&#39; ) AND speciality != &#39;计算机&#39;85 ? ?【例7.43】查询与李燕选修过相同课程的学生信息及课程 名称。 分析:可以先查询出“李燕”选修过的课程的课程号,然 后再查询其他学生是否也选修过这些课程(即课程号与 “李燕”选修过的课程号相同)。?? ?SELECT S.studentID,studentName,courseName FROM Student S JOIN Grade ON S.studentID=Grade.studentID JOIN Course C ON Grade.courseID=C.courseID WHERE C.courseID=ANY (SELECT courseID FROM Student JOIN Grade ON Student.studentID=Grade.studentID WHERE studentName=&#39;李燕&#39;)86 ?7.10.4 带EXISTS的嵌套查询EXISTS代表存在量词 ? 。带有EXISTS谓词的子查询不返回 任何数据,只产生逻辑真值“true”或逻辑假值“false”。 使用存在量词EXISTS后,若内层查询结果非空,则外层的 WHERE子句返回真值,否则,返回假值。 ? 【例7.44】查询所有选修了1号课程的学生姓名。 ? 本查询涉及Student和Grade关系。可以在Student表中依次 取每个元组的studentID值,再用这个值去检查Grade关系。 若Grade中存在这样的元组:其studentID值等于此Student 表当前的studentID值(student.studentID),并且其课 程号courseID为1;则取此当前记录的studentName送入结 果集中。?87 ?? ?SQL语句如下: SELECT studentName FROM Student WHERE EXISTS ( SELECT * FROM Grade WHERE studentID = Student.studentID AND courseID = &#39;1&#39; ) 思考:如果想查询所有选修了1号课程的学生姓名及课程成 绩,该如何实现?你能用多种方法完成该查询吗? 由前面的例子可以看出,只有当使用了EXISTS关键字时, 才在子查询的列表达式中使用星号(*)代替所有的列名。 这是因为当使用EXISTS关键字时,子查询不是返回数据, 而是判断子查询是否存在数据,这时给出列名没有实际意 义。88 ?【 例 7.44】 中 子 查 询 的 查 询 条 件 依 赖 于 外 层 父 查 询 的 studentID属性值,因此是相关子查询。求解相关子查询不 能像求解不相关子查询那样,一次将子查询求解出来。由 于内层查询与外层查询相关,因此必须反复求值。从概念 上讲,相关子查询的一般处理过程是: ? 首先取外层查询表(Student)中的第一个元组,根据 它与内存查询相关的属性值(studentID值)处理内层 查询,如果WHERE子句返回值为真,则取外层查询中该 元组放入结果表; ? 然后再取外层查询表(Student)中的下一个元组; ? 重复这一过程,直到外层查询表全部检查完为止。89 ??与EXISTS谓词相对应的是NOT EXISTS。使用存在两次NOT EXISTS后,若内层查询结果为空,则外层的WHERE子句返回 真值,否则返回假值。 【例7.45】查询所有没有选修1号课程的学生姓名。 SELECT studentName FROM Student WHERE NOT EXISTS ( SELECT * FROM Grade WHERE studentID = Student.studentID AND courseID = &#39;1&#39; )90 ? ?【例7.46】查询选修了所有全部课程的学生姓名。 查询选修了所有全部课程的学生姓名,等价于查询这样的 学生:对于这些学生,不存在任何一门课没有被选修。SQL 语句如下:SELECT studentName FROM Student WHERE NOT EXISTS (SELECT * FROM Course WHERE NOT EXISTS ( SELECT * FROM Grade WHERE studentID = Student.studentID AND courseID = Course.courseID)91 ???一些带有EXISTS或NOT EXISTS谓词的子查询不能被其他形 式的子查询等价替换,但所有带IN谓词、比较运算符、ANY 和ALL谓词的子查询都能用EXISTS谓词的子查询等价替换。 例如,带有IN谓词的【例7.39】可以用如下带EXISTS谓词 的子查询替换: SELECT studentID, studentName, speciality FROM Student S1 WHERE EXISTS ( SELECT * FROM Student S2 WHERE S2.speciality = S1.speciality AND S2.studentName = &#39;王恒&#39; ) 由于带EXISTS量词的相关子查询只关心内层查询是否有返 回值,并不需要查出具体值,因此其效率并不一定低于不 相关子查询,甚至有时还是高效的方法。92 7.11 集合运算???SELECT查询语句的结果集往往是一个包含了多行数据(元 组)的集合。在数学领域中,集合之间可以进行并、交、 差等运算。 在Microsoft SQL Server 2008中,两个查询语句之间也可 以 进 行 集 合 运 算 , 其 中 主 要 包 括 并 操 作 UNION 、 交 操 作 INTERSECT和差操作EXCEPT。需要注意的是,在进行集合运 算时,所有查询语句中的列的数量和顺序必须相同,且数 据类型必须兼容。 集合运算与连接运算是不同的。在连接运算的结果集中, 结果集中的列的数量经常会发生变化,并且行的数量也有 可能发生变化。但是,在集合运算的结果集中,结果集中 的列的数量不发生变化,只是行的数量可能发生变化。93 集合运算? ? ?7.11.17.11.2 7.11.3并操作交操作 差操作94 7.11.1 并操作? ? ? ?UNION运算符表示并集运算,结果集中包含了执行并操作的 结果集中的所有数据。 其基本格式为: ? & subquery & UNION [ALL] & subquery & 【例7.47】查询选修了课程1或者选修了课程2的学生学号。 本查询实际上就是查询选修了课程1的学生集合与选修了课 程2的学生集合的并集。 SELECT studentID FROM Grade WHERE courseID = &#39;1&#39; UNION ALL SELECT studentID FROM Grade WHERE courseID = &#39;2&#39;95 ??在查询结果集中可以看到,结果集中包含了重复数据,这 是由于查询语句中使用了ALL关键字的缘故。如果去掉ALL 使用DISTINCT关键字,则结果集中不会出现重复值。 该查询也可以用以下语句实现(不包含重复值): SELECT DISTINCT studentID FROM Grade WHERE courseID = &#39;1&#39; OR courseID = &#39;2&#39;;96 7.11.2 交操作? ? ?【例7.48】查询既选修了1号课程又选修了2号课程的学生 学号。 本查询实际上就是查询选修了1号课程的学生集合与选修了 2号课程的学生集合的交集。 SQL语句如下: SELECT studentID FROM Grade WHERE courseID = &#39;1&#39; INTERSECT SELECT studentID FROM Grade WHERE courseID = &#39;2&#39;97 该查询等价于以下语句: SELECT studentID FROM Grade X WHERE courseID = &#39;1&#39; AND EXISTS (SELECT * FROM Grade Y WHERE courseID = &#39;2&#39; AND X.studentID=Y.studentID) ? 思考:如果要查询既选修了课程1又选修了课程2的学生学 号和姓名信息的话,又该如何实现呢??98 7.11.3 差操作?【例7.49】查询没有选修课程的学生学号、姓名。 SELECT studentID,studentName FROM Student WHERE studentID IN (SELECT studentID FROM Student EXCEPT SELECT studentID FROM Grade) ? 先查询得到所有的学生学号,再从中减去(差集)所有 选修了课程的学生学号,即是没有选修课程的学生学号。 根据学生学号即可得到相应的学生姓名。 ? 本查询也可使用IN查询、EXISTS查询来实现,语句如下: SELECT studentID,studentName FROM Student WHERE NOT EXISTS (SELECT * FROM Grade WHERE Student.studentID=Grade.studentID)99 本章小结??SQL语言的数据查询功能是最丰富、也是最复杂的,本章介 绍了数据更新命令和基本的SQL查询语句,使用这些语句可 以完成数据的插入、修改和删除,以及数据查询操作,包括 基本数据查询、条件查询、嵌套查询、集合查询、连接查询、 排序查询、统计函数、分组查询等,为读者学习数据库编程 和进行数据库操作打下坚实的基础。 SQL语句查询数据的基本格式为: ? SELECT select_list [ INTO new_table ] ? [ FROM table_source ] ? [ WHERE search_condition ] ? [ GROUP BY group_by_expression] ? [ HAVING search_condition] ? [ ORDER BY order_expression [ ASC | DESC ] ]100
SQLServer2008数据库应用教程课后答案_工学_高等教育...候选码 7.关系名(属性 1,属性 2,?,属性 n) 8...以主表的每一行数据去匹配从表中的数据 列,符合...数据库系统及应用教程(SQL Server 2008)习题1-8章...2.文件系统阶段的数据管理有哪些特点? 答:文件系统...可以查询数据表中某些字段构成的数据,只是一些 SQL ...SQL Server2008数据库应用技术》-实验手册_计算机软件...第 1 章介绍了销售管理数据库开发的 环境; 第 2...3.5 销售管理数据库数据表中数据的操作 ......选择 -1- 《数据库技术与应用-SQL SERVER2005》...第五章 表的管理一、选择题 CACCC 二、填空题 1...&#39;2008-10-10&#39;,&#39;2008-12-12&#39;,200000,&#39;2008-12...《数据库技术与应用-SQL Server 2005》习题参考答案第一章 一.选择题 1.A 2...数据库中数据完整性的一种机制它定义了可输入 表或表的单个列中的数据限制条件...选择 第三章 SQL SERVER2005 系统基础一、选择题 ACBCB -3- 《数据库技术与应用-SQL SERVER2005》习题参考答案 编辑整理:江枫 二、填空题 1. 企业版,标准版...第 6 章 SQL Server 关系数据库管理系统 教学内容: 1、SQL Server 2008 的系统结构。 2、SQL Server 2008 的管理功能。 3、SQL Server 2008 的数据库操作...《SQL Server 数据库技术及应用 (2008 R2) 》 课程大纲 I 《SQL Server 数据库技术及应用(2008 R2 版) 》 课程大纲 目一、 1. 二、 录 课 ...数据库技术及应用实验指导_信息与通信_工程科技_专业...2、熟练掌握在 SQL SERVER 2008 环境下建立数据库...“对象资源管理器”中对数据表中的数据进行更新操作...数据库技术与应用SQL习题答案 实验2 SQL Server ...studentsdb 数据库 的 grade 表中学号为&#39;0004&#39;的...数据库创建一个规则,限制所输入的数据为 7 位 0-...
All rights reserved Powered by
www.tceic.com
copyright &copyright 。文档资料库内容来自网络,如有侵犯请联系客服。}

我要回帖

更多关于 sql语句insert into 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信