Oracle 数据库 - SQL 语言基础及调优(二)

目录

子查询的用法

1、什么是子查询?

2、单行子查询

3、多行子查询

1)、使用 in 运算符

2)、使用 any 运算符

3)、使用 all 运算符

4、关联子查询

操作数据库

1、插入数据

2、更新数据

3、删除数据

1)、delete 语句

2)、truncate 语句

事务处理

1、事务概述

2、操作事务

1)、提交事务(commit 语句)

2)、回滚事务(rollback 语句)


 

子查询的用法

在执行数据操作(包括查询、添加、修改和删除等操作)的过程中,如果某个操作需要依赖于另外一个 select 语句的查询结果,那么就可以把 select 语句嵌入该操作语句中,这样就形成了一个子查询。实际上,在关系型数据库中,各表之间的数据关系非常密切,它们相互关联,相互依存,这样就可以根据数据之间的关系适用相应的子查询,从而实现复杂的查询。

1、什么是子查询?

子查询是在 SQL 语句内的另外一条 select 语句,也被称为内查询或是内 select 语句。在 select 、insert 、update 或 delete 命令中允许是一个表达式的地方都可以包含子查询,子查询甚至可以包含在另外一个子查询中。

例:在 emp 表中查询部门名称为 “RESEARCH” 的员工信息,代码如下:

上述的需求也可以通过多表关联查询来实现,如下:

从上面的两段代码中可以看出,相比多表关联查询,子查询的使用更加灵活、功能更强大,而且更容易理解。但是多表关联查询的效率要高于子查询。

在一般情况下,外查询语句语句检索一行,子查询语句需要检索一遍数据,然后判断外查询语句的条件是否满足。如果条件满足,则外查询语句将检索到的数据行添加到结果集中,如果条件不满足,则外查询语句继续检索下一行数据,所以子查询相对多表关联查询要慢一些。

另外,在使用子查询时,还应注意以下规则:子查询必须用括号 “()” 括起来,子查询中不能包括 order by 子句,子查询允许嵌套多层,但不能超过255层。

 

2、单行子查询

单行子查询是指返回一行数据的子查询语句。当在 where 子句中引用单行子查询时,可以使用单行比较运算符(=、>、<、>=、<=和 <>)。

例:在 emp 表中,查询处既不是最高工资,也不是最低工资的员工信息

在上面语句中,如果内层子查询语句的执行结果为空值,那么外层的 where 子句就始终不会满足条件,这样该查询的结果就必然为空值,因为空值无法参与比较运算。

在执行单行子查询时,要注意子查询的返回结果必须是一行数据,否则 Oracle 系统会提示无法执行。另外,子查询中也不能包含 order by 子句,如果非要对数据进行排序的话,那么只能在外查询语句中使用 order by 语句

 

3、多行子查询

多行子查询是指返回多行数据的子查询语句。当在 where 子句中使用多行子查询时,必须使用多行比较符(in、any、all)。

1)、使用 in 运算符

当在多行子查询中使用 in 运算符时,外查询会尝试与子查询结果中的任何一个结果进行匹配,只要有一个匹配成功,则外查询返回当前检索的记录。

例:在 emp 表中,查询不是销售部门 (SALES)的员工信息:

 

2)、使用 any 运算符

any 运算符必须与单行操作符结合使用,并且返回行只要匹配子查询的任何一个结果即可。

例:在 emp 表中,查询工资大于部门编号为 10 的任意一个员工工资即可的其他部门的员工信息:

 

3)、使用 all 运算符

all 运算符必须与单行运算符结合使用,并且返回行必须匹配所有子查询结果。

例:在 emp 表中,查询工资大于部门编号为 30 的所有员工工资的员工信息:

 

4、关联子查询

在单行子查询和多行子查询中,内查询和1外查询是分开执行的,也就是说内查询的执行与外查询的执行是没有关系的,外查询仅仅是使用内查询的最终结果。在一些特殊需求的子查询中,内查询的执行需要借助于外查询,而外查询的执行又离不开内查询的执行,这时内查询和外查询是相互关联的,这种子查询就被称为关联子查询

例:在 emp 表中,使用 “关联子查询” 检索工资大于同职位的平均工资的员工信息

在上面的查询语句中,内层查询使用关联子查询计算每个职位的平均工资。而关联子查询必须知道职位的名称,为此外层查询就使用 e.job 字段值为内层查询提供职位名称,以便于计算出某个职位的平均工资。如果外层查询正在检索的数据行的工资高于平均工资,则该行的员工信息会显示出来,否则不显示。

在执行关联子查询的过程中,必须遍历数据表中的每条记录,因此如果被遍历的数据表中有大量数据记录,则关联子查询的执行速度会比较缓慢。需要补充一点的是,关联子查询不但可以作为 select 语句的子查询,也可以作为 insert 、update 或 delete 语句的关联子查询

 

操作数据库

使用 SQL 语句操作数据库,除了查询操作之外,还包括完成插入、更新和删除等数据操作,分别对应 insert、delete 和 update 三条语句。在 Oracle 11g 中 ,DML 除了包括上面的三种语句外,还包括 truncate 、call 、locktable 和 merge 等语句。下面主要是对 insert 、update 、delete、truncate 的常用 DML 语句进行介绍。

1、插入数据

插入数据就是将数据记录添加到已经存在的数据表中,该语句既可以实现向数据表中一次插入一条记录,也可以使用 select 子句将查询结果集批量插入数据表

在上面的示例中,insert into 子句中指定添加数据的列,既可以是数据表的全部列,也可以是部分列。在指定部分列时,需要注意不许为空(not null) 的列必须被指定出来,并且在 values 子句中的对应赋值也不许为 null ,否则系统显示 “无法将 null 插入” 的错误信息提示。在使用 insert into 子句指定为表的部分列添加数据时,为了防止产生不许为空值的错误,可以使用 desc 命令查看数据表中的哪些列不许为空。对于可以为空的列,用户可以不指定其值。另外在向表的所有列添加数据时,也可以省略 insert into 子句后面的列表清单,使用这种方法时,必须根据表中定义的列的顺序,为所有的列提供数据。用户也可以使用 desc 命令来查看表中定义列的顺序

 

2、更新数据

如果表中的数据不正确或者不符合要求,那么就需要对其进行修改。Oracle 数据库通过 update 语句来实现修改现有的数据记录。在更新数据时,更新的列数可以由用户自己指定,列与列之间用逗号 (“,”)分隔;更新的条数可以通过 where 子句来加以限制,使用 where 子句时,系统只更新符合 where 条件的记录信息。

在上面的代码中,update 语句更新记录的数量是通过 where 子句来实现控制的,若取消 where 子句的限制,则系统会将 emp 表中所有人员的工资都上调 20%。另外,同 insert 语句一样,update 语句也可以与 select 语句组合使用达到更新数据的目的

例:在 scott 模式下,把 emp 表中工资小于 2000 的雇员工资调整为管理者的平均工资水平:

上面语句需要注意的是,在将 update 语句与 select 语句组合使用时,必须保证 select 语句返回单一的值,否则会出现错误提示,导致更新数据失败。

 

3、删除数据

在 Oracle 数据库中,删除记录可以使用 delete 语句和 truncate 语句,但这两种语句有很大区别,下面进行讲解。

1)、delete 语句

该语句用来删除数据库中的所有记录和指定范围的记录,若要删除指定范围的记录,同 update 语句一样,要通过 where 子句进行限制。

在上面的代码中,delete 语句删除记录的数量是通过 where 子句实现控制的,这里限制只删除部门编号是 10 的记录,若取消 where 子句的限制,则系统会将 emp 表中所有人员的记录都删除。使用 delete 语句删除数据时,Oracle 系统会产生回滚记录,所以这种操作可以使用 rollback 语句来撤销

 

2)、truncate 语句

如果用户确定要删除表中偶读所有记录,除了可以使用 delete 语句之外,还可以使用 truncate 语句,而且 Oracle 本身也建议使用 truncate 语句

使用 truncate 语句删除表中的所有记录要比 delete 语句快得多。这是因为使用 truncate 语句删除数据时,它不会产生回滚记录。当然执行了 truncate 语句的操作也就无法使用 rollback 语句撤销。

 

事务处理

事务是由一系列语句构成的逻辑工作单元。事务和存储过程等批处理有一定程度上的相似之处,通常都是为了完成一定业务逻辑而将一条或者多条语句 “封装” 起来,使它们与其他语句之间出现一个逻辑上的边界,并形成相对独立的一个工作单元

1、事务概述

当使用事务修改多个数据表时,如果在处理的过程中出现了某种错误,例如,系统死机或突然断电等情况,则返回结果是数据全部没有被保存。因为事务处理的结果只有两种:一种是在事务处理的过程中,如果发生了某种错误则整个事务全部回滚,使所有对数据的修改全部撤销,事务对数据库的操作都是单步执行的,当遇到错误时可以随时地回滚;另一种是如果没有发生任何错误且每一步的执行都成功,则整个事务全部被提交。从而可以看出,有效地使用事务不但可以提高数据的安全性,而且还可以增强数据的处理效率。

事务包含四个重要的属性,被统称为 ACID (原子性、一致性、隔离性和持久性)一个事务必须通过 ACID。1)、原子性:事务是一个整体的工作单元,事务对数据库所做的操作要么全部执行,要么全部取消。如果某条语句执行失败,则所有语句全部回滚。2)、一致性:事务在完成时,必须使所有的数据都保持一致状态。在相关数据库中,所有规则都必须应用于事务的修改,以保持所有数据的完整性。如果事务成功,则所有数据将变成一个新的状态;如果事务失败,则所有数据将处于开始之前的状态。3)、隔离性:由事务所作的修改必须与其他事务所作的修改隔离。事务查看数据时数据所处的状态,要么是另一并发事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看中间状态的数据。4)、持久性:当事务提交后,对数据库所作的修改就会永久保存下来。

 

2、操作事务

Oracle 11g 中的事务是隐式自动开始的,它不需要用户显式地执行开始事务语句。但对于事务的结束处理,则需要用户进行指定的操作通常在以下情况时,Oracle 认为一个事务结束了

1)、执行 commit 语句提交事务;2)、指定 rollback 语句撤销事务;3)、执行一条数据定义语句,如 create、drop 或 alter 等语句。如果该语句执行成功,那么 Oracle 系统会自动执行 commit 命令;否则自动执行 rollback 命令;4)、执行一个数据控制命令,如 grant。revoke 等控制命令,这种操作执行完毕,Oracle 系统会自动执行 commit 命令;5)、正常地断开数据库的连接、正常地退出 sql*plus 环境、则 Oracle 系统会自动执行 commit 命令,否则自动执行 rollback 命令。

综合上面5种情况可知,Oracle 结束一个事务归根结底,要么执行 commit 语句,要么执行 rollback 语句

1)、提交事务(commit 语句)

提交事务是指把对数据库进行的全部操作持久性地保存到数据库中,这种操作通常使用 commit 语句来完成。在使用该语句提交事务时,Oracle 系统内部会按照如下顺序进行处理:1)、首先在回滚段内记录当前事务已提交,并且声称一个唯一的系统该编号(SCN),以唯一标识这个事务;2)、然后启动后台的日志写入进程(LGWR),将 SGA 区的重做日志缓冲区中的数据和当前事务的 SCN 写入重做日志文件中;3)、接着 Oracle 服务器开始释放事务处理所使用的系统资源;4)、最后显示通知,告诉用户事务已经成功提交完毕。

在上面示例中,如果不使用 commit 提交事务,此时再开启一个新的 sql*plus 环境(但要求当前的 sql*plus 环境不退出,若退出,Oracle 系统会自动执行 commit 语句提交数据库),然后查询该表,会发现新增加的记录不存在。而若使用 commit 语句提交事务,则在另一个 sql*plus 环境下就能够查询到新增加的记录。

 

2)、回滚事务(rollback 语句)

回退事务是指撤销对数据库进行的全部操作,Oracle 利用回退段来存储修改前的数据,通过重做日志来记录对数据所作的修改。如果要回退整个事务,Oracle 系统内部将会执行如下操作过程:1)、首先使用回退段中的数据撤销对数据库所做的修改;2)、然后 Oracle 后台服务进程释放掉事务所使用的系统资源;3)、最后显示通知,告诉用户事务回退成功。

Oracle 不仅允许回退整个未提交的事务,还允许回退事务的一部分,这是可以通过 “保存点” 来完成。在事务的执行过程中,用户可以通过建立保存点将一个较长的事务分隔为几部分,这样用户就可以有选择性地回退到某个保存点,并且该保存点之后的操作都将被取消。

例:新建 stu 表,向表中先后添加两条数据,使用保存点 (savepoint)回滚最后添加的记录

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值