上一章介绍了如何向表中插入数据,本章将主要讨论通过UPDATE 和DELETE语句更新和删除表中的数据。 12.1 更新表中的数据在SQL中,可以使用UPDATE语句来修改表中的现有数据,也称为更新数据库表中的数据。 12.1.1 UPDATE语句的基本语法使用UPDATE语句,一次可以改变数据库表中单行上的值,也可以改变表中选定的一些行上的多列数据,当然也可以更新所有行的数据。语法如下。 UPDATE table_name SET column1=value1, column2=value2, …… WHERE search_condition 说明:UPDATE语句实际上主要包括三部分:要更新的表名、列名和它们的新值以及选择更新行的搜索条件。 UPDATE语句中的WHERE子句确定表(table_name)中要修改的数据行。SET子句提供要修改的列值的清单。简单来讲,UPDATE语句执行时,一次一行地处理整个表,更新那些搜索为True(即WHERE子句为True)的行上的SET子句列出的列值。UPDATE语句把那些搜索条件为False或NULL的行中的数据保持不变。 由UPDATE的语法可见,SET子句包括了列赋值表达式的清单。表列名在赋值清单中作为赋值目标只能出现一次。并且表达式必须要产生一个与要赋值的列的数据类型相兼容的值。
12.1.2 UPDATE语句更新列值使用UPDATE语句可以更新单列数据也可以更新多列数据。下面通过几个实例介绍一下使用UPDATE语句更新列值的操作。 实例1 复制TEACHER表数据到新表 本节所有的更新实例均是基于TEACHER表(参见本书5.2.1节的表5-1)中的数据进行的,为了不影响TEACHER表的其他应用,这里用第11章介绍的SELECT……INTO语句将TEACHER表中的数据复制到New_Teacher表中。本节给出的更新操作实例均是针对New_Teacher表进行的。代码如下。 SELECT * INTO New_Teacher FROM TEACHER 查看表New_Teacher的数据。 SELECT * FROM New_Teacher 运行结果如图12.1所示。 图12.1 New_Teacher表中的记录 1.更新单列数据实例2 更新单列数据 “三八”节到了,该月为所有女教师的工资增加100元过节费。实例代码: UPDATE New_Teacher SET SAL=SAL+100 WHERE TSEX='女' 查看表New_Teacher的数据。 SELECT * FROM New_Teacher 运行结果如图12.2所示。 图12.2 女教师的工资增加100元后的纪录 可见,表中所有女教师SAL列的数据都增加了100,而其他数据都没有改变。需要注意的是教工号为8和10的两个女教师的SAL列数据仍为NULL,这是因为NULL值参与任何数学运算其结果仍为NULL,因此“NULL+100”结果仍为NULL。 2.多列数据的更新使用UPDATE语句一次也可以更新多列数据,只要写入SET子句的更新清单中即可。 实例3 多列数据的更新 新的一年开始了,所有教师的年龄增加了1岁,同时给所有教师的工资增加10%。实例代码如下。 (1)先将女教师的工资恢复到原来值。 UPDATE New_Teacher SET SAL=SAL-100 WHERE TSEX=’女’ (2)更新所有教师的年龄和工资信息。 UPDATE New_Teacher SET AGE = AGE +1, SAL= SAL*1.1 (3)查看表New_Teacher的数据。 SELECT * FROM New_Teacher 运行结果如图12.3所示。 可见,所有的SAL列和AGE列的数据都发生了改变。 图12.3 更新表New_Teacher后的纪录 3.通过更新删除列中的数据有时候需要通过数据的更新操作,实现删除某列数据的目的。通常的做法是把该列的值设置为NULL。当然,这样做的前提是该列允许为空值,即没有非空约束。 实例4 通过更新删除列中的数据 生物系教师的工资进行了调整,目前还不知道调整后的具体工资,因此需要把其原有的工资信息删除。实例代码: UPDATE New_Teacher SET SAL = NULL WHERE DNAME ='生物' 查看表New_Teacher的数据。 SELECT * FROM New_Teacher 运行结果如图12.4所示。 图12.4 将生物系教师原有的工资信息删除 可见,生物系所有的教师的SAL列值都变为NULL。
例如上例,执行数据更新前,确定一些更新操作影响的行数,即所有生物系教师的记录数,代码如下。 SELECT COUNT(*) FROM New_Teacher WHERE DNAME ='生物' 运行结果如图12.5所示。 图12.5 生物系教师的记录数 由此可知,UPDATE语句将更新New_Teacher表中的两行数据,这样有利于减少更新操作的错误概率。 12.1.3 利用子查询更新多行的值在UPDATE语句的WHERE子句中,可以使用比较运算符(=、>、<、>=、<=、<>)来确定搜索条件,同样也可以使用子查询来确定需要更新的行。下面就结合具体的实例说明其应用。 实例5 复制TEACHER表数据到新表 同样,为了不影响TEACHER表中的原始数据,需要将TEACHER表中的数据复制到表New_Teacher2表中。这样,直接操作New_Teacher2表就可以了。代码如下。 SELECT * INTO New_Teacher2 FROM TEACHER 查看表New_Teacher2的数据。 SELECT * FROM New_Teacher2 运行结果如图12.6所示。 图12.6 将TEACHER表中的数据复制到表New_Teacher2表 实例6 利用子查询更新多行的值 在NEW_ Teacher2表中,当男教师的工资少于所有男教师的平均工资时,将该男教师的工资提高5%。实例代码: UPDATE NEW_Teacher2 SET SAL = SAL +SAL * 0.05 WHERE TSEX='男' AND SAL < (SELECT avg(SAL) FROM NEW_Teacher2 WHERE TSEX='男') 查看更新后表New_TEACHER2中的数据。 SELECT * FROM New_TEACHER2 运行结果如图12.7所示。 图12.7 将工资少于所有男教师的平均工资的男教师的工资提高5% 可以发现,教工号为1、3、6的男教师的SAL列数据进行了更新,其余数据均没有发生变化。 特别需要强调一点,使用子查询选择要更新的行时,可以在子查询中引用正在更新的表,如本例中,子查询语句就引用了表NEW_Teacher2。这时,子查询引用的表中的数据都认为是更新前的数据。 如在该实例中,代码执行时,DBMS首先读出NEW_Teacher2表中的第一行记录,经验证其满足WHERE子句中的搜索条件,就将其SAL列中的数据更新,即由800更新为840。而后系统从NEW_Teacher2表取出第二条记录,此时在WHERE子句中执行子查询即使用AVG聚合函数,其中要用到第一条记录的SAL列中的数据,这时采用的是更新前的数据,即仍然为800。也就是说,在整个UPDATE语句执行期间,子查询中的AVG函数得到的值始终是相同的。 12.1.4 依据外表值更新数据虽然UPDATE语句只允许改变单个表中的列值,但在UPDATE语句的WHERE子句中可以使用任何可用的表。因此可根据别的表中的相关值来决定目标表中要更新的数据行。 实例7 依据外表值更新数据 在NEW_Teacher2表中,将所授课程学时超过40个(COURSE表),或者是在STUDENT表中其所授课程的成绩存在优秀(超过85分)的教师发放100元的奖金。实例代码: UPDATE NEW_Teacher2 SET SAL = SAL +100 WHERE CNO IN (SELECT CNO FROM COURSE WHERE CNO = NEW_Teacher2.CNO AND CTIME >= 40) OR CNO IN (SELECT CNO FROM STUDENT WHERE CNO = NEW_Teacher2.CNO GROUP BY CNO HAVING MAX(MARK) >= 85) 查看更新后表New_TEACHER2中的数据。 SELECT * FROM New_TEACHER2 运行结果如图12.8所示。 图12.8 依据外表值更新数据 对比更新前后NEW_Teacher2表中的数据,共有5行记录(1、3、4、6、9)的SAL列数据进行了更新。 12.1.5 分步更新表有时对数据库表中的数据完成某种更新操作,需要使用UPDATE语句分几步完成,这时特别需要注意数据更新的顺序。 实例8 分步更新表 在NEW_Teacher2表中,工资超过1500的缴纳10%所得税,超过800的缴纳5%所得税,其余的不缴税。重新计算缴税后各教师的工资。实例代码: UPDATE NEW_Teacher2 SET SAL = SAL * 0.95 WHERE SAL <= 1500 AND SAL >800 /*继续更新大于1500的工资*/ UPDATE NEW_Teacher2 SET SAL = SAL * 0.9 WHERE SAL >1500 查看更新后表NEW_Teacher2的数据。 SELECT * FROM NEW_Teacher2 运行结果如图12.9所示。 图12.9 分步更新NEW_Teacher2表后的纪录 上面的两个UPDATE语句的执行顺序是正确的,而如果将两个UPDATE语句的执行顺序颠倒,则可能会造成执行结果错误,其中原因读者可自行分析。 |
|
来自: 昵称310935 > 《oracle相关文档》