当前位置:  数据库>sqlserver

sql中update子查询的实例解析

    来源: 互联网  发布时间:2014-08-29

    本文导语:  本节内容: update子查询的相关知识 基础知识 1,关联子查询和非关联子查询 在非关联子查询中,内部查询只执行一次并返回它的值给外部查询,然后外部查询在它的处理中使用内部查询返回给它的值。 而在关联子查询中,...

本节内容:
update子查询的相关知识

基础知识
1,关联子查询和非关联子查询
在非关联子查询中,内部查询只执行一次并返回它的值给外部查询,然后外部查询在它的处理中使用内部查询返回给它的值。

而在关联子查询中,对于外部查询返回的每一行数据,内部查询都要执行一次。

另外,在关联子查询中是信息流是双向的。

外部查询的每行数据传递一个值给子查询,然后子查询为每一行数据执行一次并返回它的记录。然后,外部查询根据返回的记录做出决策。

例如:

1)、关联子查询:
 

代码示例:
SELECT o1.CustomerID, o1.OrderID, o1.OrderDate
FROM Orders o1
WHERE o1.OrderDate = (SELECT Max(OrderDate)
FROM Orders o2
WHERE o2.CustomerID = o1.CustomerID)

2)、非关联子查询:
 

代码示例:
SELECT o1.CustomerID, o1.OrderID, o1.OrderDate
FROM Orders o1
WHERE o1.OrderDate IN
(SELECT TOP 2 o2.OrderDate
FROM Orders o2
WHERE o2.CustomerID = o1.CustomerID)
ORDER BY CustomerID

2, 提示(HINT)
一般在优化时,无论采用基于规则的或是基于代价的方法,由Oracle系统的优化器来决定语句的执行路径。

这样的选择的路径不要见得是最好的。所以,Oracle提供了一种方法叫提示的方法。

它可以让编程人员按照自己的要求来选择执行路径,即提示优化器该按照什么样的执行规则来执行当前的语句。

这样可以在性能上比起Oracle优化自主决定要好些。

通常情况下,编程人员可以利用提示来进行优化决策。

通过运用提示可以对下面内容进行指定:
 

1,SQL语句的优化方法;
2,对于某条SQL语句,基于开销优化程序的目标;
3,SQL语句访问的访问路径;
4,连接语句的连接次序;
5,连接语句中的连接操作。

如果希望优化器按照编程人员的要求执行,则要在语句中给出提示。提示的有效范围有限制,即有提示的语句块才能按照提示要求执行。

指定提示:
1,简单的SELECT ,UPDATE ,DELETE 语句;
2,复合的主语句或子查询语句;
3,组成查询(UNION)的一部分。

提示的指定有原来的注释语句在加“+”构成。
语法如下:
[ SELECT | DELETE|UPDATE ] /*+ [hint | text ] */

[ SELECT | DELETE|UPDATE ] --+ [hint | text ]
注意,在“/*”后不要空就直接加“+”,同样 “--+”也是连着写。
警告:如果该提示语句书写不正确,则Oracle就忽略掉该语句。

常见的提示有:
 

Ordered 强制按照from子句中指定的表的顺序进行连接
Use_NL 强制指定两个表间的连接方式为嵌套循环(Nested Loops)
Use_Hash 强制指定两个表间的连接方式为哈希连接(Hash Join)
Use_Merge 强制指定两个表间的连接方式为合并排序连接(Merge Join)
Push_Subq 让非关联子查询提前执行
Index 强制使用某个索引

3, 执行计划
在PL/SQL Developer的SQL WINDOWS中用鼠标或键盘选中SQL语句,然后按F5,就会出现执行计划解析的界面:

4, Update的特点
Update的系统内部执行情况可以参照附文:对update事务的内部分析.doc

使用Update的基本要点就是,
1) 尽量使用更新表上的索引,减少不必要的更新
2) 更新的数据来源花费时间尽可能短,如果无法做到就把更新内容插入到中间表中,然后给中间表建上索引,再来更新
3) 如果更新的是主键,建议删除再插入。

5, 示例用表
后面的阐述将围绕以下两张表展开:
 

代码示例:
Create table tab1 (workdate varchar2(8), cino varchar2(15), val1 number, val2 number);
Create table tab2 (workdate varchar2(8), cino varchar2(15), val1 number, val2 number);
Create table tab3 (workdate varchar2(8), cino varchar2(15), val1 number, val2 number);
Create table tab4 (workdate varchar2(8), cino varchar2(15), val1 number, val2 number);workdate, cino为两张表的关键字,默认情况没有建主键索引。

二,Update两种情况

用Update更新某个表,无外乎是两种情况:根据关联子查询,更新字段;通过非关联子查询,限定更新范围。如果还有第三种情况,那就是前两种情况的叠加。

1, 根据关联子查询,更新字段
 

代码示例:
Update tab1 t
Set (val1, val2) = (select val1, val2
from tab2
where workdate = t.workdate
and cino = t.cino);

通过tab2来更新tab1的相应字段。执行SQL语句时,系统会从tab1中一行一行读记录,然后再通过关联子查询,找到相应的字段来更新。关联子查询能否通过tab1的条件快速的查找到对应记录,是优化能否实现的必要条件。所以一般都要求在tab2上建有Unique或者排重性较高的Normal索引。执行所用时间大概为(查询tab1中一条记录所用的时间 + 在tab2中查询一条记录所用的时间)* tab1中的记录条数。

如果子查询条件比较复杂,如以下语句:
 

代码示例:
Update tab1 t
Set (val1, val2) = (select val1, val2
from tab2 tt
where exists (select 1
from tab3
where workdate = tt.workdate
and cino = tt.cino)
and workdate = t.workdate
and cino = t.cino);

这时更新tab1中的每条记录花费在子查询上的时间将成倍增加,如果tab1中的记录数较多,这种更新语句几乎是不可完成。

解决方法:
把子查询提取出来,做到中间表中,然后给中间表建上索引,用中间表来代替子查询,这样速度就能大大提高:
 

代码示例:

Insert into tab4
select workdate, cino, val1, val2
from tab2 tt
where exists (select 1
from tab3
where workdate = tt.workdate
and cino = tt.cino);
create index tab4_ind01 on tab4(workdate, cino);

Update tab1 t
Set (val1, val2) = (select val1, val2
from tab4 tt
where workdate = t.workdate
and cino = t.cino);

2, 通过非关联子查询,限定更新范围
 

代码示例:
Update tab1 t
set val1 = 1
where (workdate, cino) in (select workdate, cino from tab2)

根据tab2提供的数据范围,来更新tab1中的相应记录的val1字段。

在这种情况下,系统默认执行方式往往是先执行select workdate, cino from tab2子查询,在系统中形成系统视图,然后在tab1中选取一条记录,查询系统视图中是否存在相应的workdate, cino组合,如果存在,则更新tab1,如果不存在,则选取下一条记录。

这种方式的查询时间大致等于:子查询查询时间 + (在tab1中选取一条记录的时间 + 在系统视图中全表扫描寻找一条记录时间)* tab1的记录条数。其中“在系统视图中全表扫描寻找一条记录时间”会根据tab2的大小而有所不同。

若tab2记录数较小,系统可以直接把表读到系统区中;
若tab2记录数多,系统无法形成系统视图,这时会每一次更新动作,就把子查询做一次,速度会非常的慢。

针对这种情况的优化有两种:
1) 在tab1上的workdate, cino字段上加入索引,同时增加提示。
修改后的SQL语句:
 

代码示例:
Update /*+ordered use_nl(sys, t)*/ tab1 t
set val1 = 1
where (workdate, cino) in (select workdate, cino from tab2)

其中sys表示系统视图。如果不加入ordered提示,系统将会默认以tab1表作为驱动表,这时就要对tab1作全表扫描。加入提示后,使用系统视图,即select workdate, cino from tab2,作为驱动表,在正常情况下,速度能提高很多。

2) 在tab2表上的workdate, cino字段加入索引,同时改写SQL语句:
 

代码示例:
Update tab1 t
set val1 = 1
where exists (select 1
from tab2
where workdate = t.workdate
and cino = t.cino)

三,索引问题
update索引的使用比较特殊,有时看起来能用全索引,但实际上却只用到一部分,所以建议把复合索引的各字段写在一起。

例如:
 

代码示例:
Update /*+ordered use_nl(sys, t)*/ tab1 t
set val1 = 1
where cino in (select cino from tab2)
and workdate = '200506'

这条SQL语句是不能完全用到tab1上的复合索引workdate + cino的。
能用到的只是workdate=’200506’的约束。

写成如下形式,就没问题:
 

代码示例:
Update /*+ordered use_nl(sys, t)*/ tab1 t
set val1 = 1
where (workdate, cino) in (select workdate, cino from tab2)

    
 
 

您可能感兴趣的文章:

  • sql语句实例 取得日志条目的sql语句
  • SQL分组排序去除重复实例
  • php防止sql注入代码实例
  • T-SQL实例 函数结果设置为列别名
  • 怎样不执行SELECT SQL语句即可获得ResultSetMetaData实例????
  • sql语句实例 统计一个特定页面中的相关链接
  • SQL分组排序去重复的小实例
  • sql语句实例 统计页面链接的sql语句
  • 教你怎么使用sql游标实例分享
  • mysqli多条sql语句查询实例
  • MSSQL中递归SQL查询语句实例说明-
  • sql语句not and or执行顺序(实例解析)
  • Sql Server中存储过程中输入和输出参数(简单实例 一看就懂)
  • SQL语句练习实例之七 剔除不需要的记录行
  • SQL cursor用法实例
  • sql server 触发器实例(判断是插入、删除,还是修改)
  • sql中获取分组排序后数据方法实例
  • 移动开发 iis7站长之家
  • sql server 触发器实例:特定字段更新时触发Update触发器
  • sql语句like多个条件的写法实例
  • oracle SQL解析步骤小结
  • MySQL的SQL语法解析器 DBIx-MyParse
  • SQL解析类库 SQLJEP
  • 解析MYSQL 数据库导入SQL 文件出现乱码的问题
  • Oracle中DBMS_SQL解析SQL语句的流程
  • 解析:清除SQL被注入恶意病毒代码的语句
  • 解析关于SQL语句Count的一点细节
  • 解析PL/SQL Developer导入导出数据库的方法以及说明
  • SQL分组查询实例解析
  • SQL_Server全文索引的用法解析
  • SQL嵌套查询示例解析
  •  
    本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • java命名空间java.sql接口resultset的类成员方法: concur_updatable定义及介绍
  • sql update 触发器 可获得被update的行的信息
  • java命名空间javax.sql.rowset.spi类syncprovider的类成员方法: updatable_view_sync定义及介绍
  • 菜鸟问题!如何update?Java+SQL server
  • java命名空间javax.sql.rowset.spi接口syncresolver的类成员方法: update_row_conflict定义及介绍
  • 如何判断一条sql(update,delete)语句是否执行成功
  • 谁能告诉我sql语言中的update怎么用呀?
  • sql多表级联更新update的用法举例
  • sql server执行update语句超级慢的原因与解决方法
  • SQL Server 触发器 表的特定字段更新时,触发Update触发器
  • ORACLE SQL-UPDATE、DELETE、INSERT优化和使用技巧分享
  • SQL Server UPDATE语句的用法详解
  • Mysql跨表更新 多表update sql语句总结
  • 标准sql update语句三种方法
  • sql中update select语句用法
  • sql中update语句的基本用法
  • sql语句中update select语句用法
  • SQL语句详解 MySQL update的正确用法
  • sql server与mysql中update多条数据
  • 执行一条sql语句update多条记录实现思路
  • 一条sql语句update更新多条记录教程详解
  • java命名空间java.sql接口statement的类成员方法: executeupdate定义及介绍
  • 请问,这是什么错误!java.sql.SQLException: [Microsoft][ODBC SQL Server Driver][Named Pipes]??????? SQL Server?虽然分少,但一定给,只要您是前5名回复者中最好的以为!
  • java命名空间java.sql接口connection的类成员方法: nativesql定义及介绍
  • SQL查询分析工具 SQL Workbench/J
  • java命名空间java.sql接口preparedstatement的类成员方法: executeupdate定义及介绍
  • oracle导出sql语句的结果集和保存执行的sql语句(深入分析)
  • java命名空间java.sql接口rowid的类成员方法: getbytes定义及介绍
  • SQL Server统计SQL语句执行时间的脚本
  • java命名空间java.sql接口ref的类成员方法: getbasetypename定义及介绍
  • SQL客户端软件 PKLite SQL Client


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3