oracle sql语句执行顺序
- 格式:doc
- 大小:63.00 KB
- 文档页数:7
Oraclesql语句执⾏顺序sql语法的分析是从右到左⼀、sql语句的执⾏步骤:1)词法分析,词法分析阶段是编译过程的第⼀个阶段。
这个阶段的任务是从左到右⼀个字符⼀个字符地读⼊源程序,即对构成源程序的字符流进⾏扫描然后根据构词规则识别单词(也称单词符号或符号)。
词法分析程序实现这个任务。
词法分析程序可以使⽤lex等⼯具⾃动⽣成。
2)语法分析,分析语句的语法是否符合规范,衡量语句中各表达式的意义。
3)语义分析,检查语句中涉及的所有数据库对象是否存在,且⽤户有相应的权限。
4)视图转换,将涉及视图的查询语句转换为相应的对基表查询语句。
5)表达式转换,将复杂的 SQL 表达式转换为较简单的等效连接表达式。
6)选择优化器,不同的优化器⼀般产⽣不同的“执⾏计划”7)选择连接⽅式, ORACLE 有三种连接⽅式,对多表连接 ORACLE 可选择适当的连接⽅式。
8)选择连接顺序,对多表连接 ORACLE 选择哪⼀对表先连接,选择这两表中哪个表做为源数据表。
9)选择数据的搜索路径,根据以上条件选择合适的数据搜索路径,如是选⽤全表搜索还是利⽤索引或是其他的⽅式。
10)运⾏“执⾏计划”⼆、oracle 共享原理:ORACLE将执⾏过的SQL语句存放在内存的共享池(shared buffer pool)中,可以被所有的数据库⽤户共享。
当你执⾏⼀个SQL语句(有时被称为⼀个游标)时,如果它和之前的执⾏过的语句完全相同,ORACLE就能很快获得已经被解析的语句以及最好的执⾏路径.。
这个功能⼤⼤地提⾼了SQL的执⾏性能并节省了内存的使⽤。
三、oracle 语句提⾼查询效率的⽅法:1:where column in(select * from ... where ...);2:... where exists (select 'X' from ...where ...);第⼆种格式要远⽐第⼀种格式的效率⾼。
在Oracle中可以⼏乎将所有的IN操作符⼦查询改写为使⽤EXISTS的⼦查询。
Oracle执⾏SQL查询语句的步骤
sql语句的执⾏主要由⽤户进程与服务器进程来完成,其他的⼀些进程可能要辅助完成这⼀过程。
查询语句与其他的sql语句有所不同,如果⼀个查询语句执⾏成功,就要返回查询结果,⽽其他的sql语句只是返回执⾏成功或失败的信息。
查询语句的主要
SQL语句的执⾏主要由⽤户进程与服务器进程来完成,其他的⼀些进程可能要辅助完成这⼀些过程。
查询语句与其他的SQL语句有所不同,如果⼀个查询语句执⾏成功,就要返回查询结果,⽽其他的SQL语句只是返回执⾏成功或执⾏失败的信息。
查询语句的处理主要包括以下3个阶段:编译,执⾏和提取数据。
编译:在进⾏编译时,服务器进程将SQL语句的正⽂放⼊共享池的库⾼速缓存中并将完成以下处理。
1.⾸先在共享池中搜索是否有相同的SQL语句,如果没有就进⾏后续的处理。
2.检查该SQL语句的语法是否正确
3.通过查看数据字典来检查表和列的定义
4.对所操作的对象加编译锁,以便在编译语句期间这些对象的定义不能被改变
5.检查锁引⽤对象的权限
6.⽣成执⾏该SQL语句所需要的优化的执⾏条件
7.将SQL语句的执⾏计划装⼊共享的SQL区
执⾏:oracle服务器进程开始执⾏SQL语句是因为它已获得了执⾏SQL语句所需要的全部资源和信息。
提取数据:oracle服务器进程所选择所需的数据⾏,并在需要时将其排序,最后将结果返回给⽤户。
ORACLESQL语句执行流程与顺序原理解析在ORACLESQL中,执行一个SQL语句的流程和顺序如下:1.语法分析:首先,ORACLE会对SQL语句进行语法分析,检查语法的正确性和完整性。
如果SQL语句存在语法错误,ORACLE会报错并中止执行。
2.词法分析:在语法分析之后,ORACLE会对SQL语句进行词法分析,将语句分解为最小的语义单元,如关键字、表名、列名等。
这些语义单元被存储在内部数据结构中,以供后续处理使用。
3.查询优化:在语法和词法分析之后,ORACLE会进行查询优化,以确定最佳的执行计划。
查询优化是一个复杂的过程,其中包括确定表的访问顺序、连接顺序、选择合适的索引等。
ORACLE会根据统计信息和系统设置来评估每个可能的执行计划,并选择成本最低的执行计划作为最终的执行方案。
4.查询执行:一旦确定了最佳的执行计划,ORACLE就开始执行SQL查询。
查询执行过程通常包括以下步骤:a.打开表:根据执行计划,ORACLE会按照指定的顺序打开需要查询的表。
b.获取数据:ORACLE会根据执行计划从打开的表中获取需要的数据。
这个过程包括索引的查找、数据块的读取等。
c.执行操作:一旦获取到数据,ORACLE会执行SQL语句中指定的操作,如查询、插入、更新等。
这些操作会在内存中进行,直到事务提交或回滚。
d.关闭表:当查询完成后,ORACLE会关闭查询过程中打开的表,释放相关的资源。
5.结果返回:最后,ORACLE将查询的结果返回给客户端。
这些结果可以是查询结果集、插入、更新的行数等。
总结起来,ORACLESQL语句的执行流程可以简单概括为语法分析、词法分析、查询优化、查询执行和结果返回。
这个过程确保了SQL语句的正确性和效率。
oracle-SQL语句执行原理和完整过程详解SQL 语句执行过程详解一条 sql,plsql 的执行到底是怎样执行的呢?一、SQL 语句执行原理:第一步:客户端把语句发给服务器端执行当我们在客户端执行select 语句时,客户端会把这条SQL 语句发送给服务器端,让服务器端的进程来处理这语句。
也就是说,Oracle 客户端是不会做任何的操作,他的主要任务就是把客户端产生的一些 SQL 语句发送给服务器端。
虽然在客户端也有一个数据库进程,但是,这个进程的作用跟服务器上的进程作用事不相同的。
服务器上的数据库进程才会对SQL 语句进行相关的处理。
不过,有个问题需要说明,就是客户端的进程跟服务器的进程是一一对应的。
也就是说,在客户端连接上服务器后,在客户端与服务器端都会形成一个进程,客户端上的我们叫做客户端进程;而服务器上的我们叫做服务器进程。
第二步:语句解析当客户端把 SQL 语句传送到服务器后,服务器进程会对该语句进行解析。
同理,这个解析的工作, 也是在服务器端所进行的。
虽然这只是一个解析的动作,但是,其会做很多“小动作”。
1. 查询高速缓存(library cache)。
服务器进程在接到客户端传送过来的SQL 语句时,不会直接去数据库查询。
而是会先在数据库的高速缓存中去查找,是否存在相同语句的执行计划。
如果在数据高速缓存中,则服务器进程就会直接执行这个SQL 语句,省去后续的工作。
所以,采用高速数据缓存的话,可以提高SQL 语句的查询效率。
一方面是从内存中读取数据要比从硬盘中的数据文件中读取数据效率要高,另一方面,也是因为这个语句解析的原因。
不过这里要注意一点,这个数据缓存跟有些客户端软件的数据缓存是两码事。
有些客户端软件为了提高查询效率,会在应用软件的客户端设置数据缓存。
由于这些数据缓存的存在,可以提高客户端应用软件的查询效率。
但是,若其他人在服务器进行了相关的修改,由于应用软件数据缓存的存在,导致修改的数据不能及时反映到客户端上。
Oracle执行语句时,对语句执行的步骤如下:1。
语法检查查看关键字等有无拼错的情况2。
语义检查查看对应的表是否存在及用户是否有需要的某种权限3。
解析利用Oracle的内部hash算法,对每一句执行的sql生成对应的hash值,存放于库缓存中 library cache。
执行的所有sql存放于library cache中4。
执行,返回结果硬解析与软解析就发生在第三步中。
软解析:根据Oracle的hash算法获取该sql的hash值,然后到library cache中查找看是否存在,如果存在,再到library cache中比对sql是否存在,如果存在,就利用已有的解析树和执行计划来执行返回结果硬解析:对执行的sql创建解析树及执行计划。
故我们在编写SQL语句时,尽量减少访问数据库的次数。
在一个查询中尽量多的把需要的值都查不来,减少数据库的工作量,使用变量Eg:查询工号为X0894、X0776对应的员工信息方法1(最低效): select empno,empname,empdepartnoFrom EMPWhere empno=’X0894’;select empno,empname,empdepartnoFrom EMPWhere empno=’X0776’;方法2(最高效):declare vn_empno1 := 'X0894',vn_empno2 := 'X0776'select empno,empname,empdepartnoFrom EMPWhere empno=vn_empno1OR empno=vn_empno2;多表关联查询时,表的顺寻及where条件顺序Oracle的解析器采用从右至左的顺序处理From后面的表名,写在最后的表将最先被处理,我们通常把最后一张表叫做基表,基表中数据要尽量的少。
处理步骤:1.扫描基表中数据并排序2.扫描倒数第二张表,将检索出的记录与基表中合适的数据进行合并针对连接表超过2张表的查询,要把交叉表当做基表来处理。
sql 条件的先后顺序
(原创版)
目录
1.SQL 条件语句的执行顺序
2.MySQL 和 Oracle 中条件执行的先后顺序
3.WHERE 子句中操作符的优先级
正文
在 SQL 语句中,条件语句的执行顺序对于查询结果至关重要。
不同
的数据库系统可能具有不同的执行顺序。
本文将介绍 MySQL 和 Oracle 中条件执行的先后顺序以及 WHERE 子句中操作符的优先级。
首先,针对 MySQL,其条件执行顺序是从左往右,自上而下。
这意味着 MySQL 会按照 WHERE 子句中条件的顺序依次执行,从第一个条件开始,如果满足则继续执行下一个条件,直至找到满足所有条件的记录。
而对于 Oracle,其条件执行顺序则是从右往左,自下而上。
这意味
着 Oracle 会首先执行最后一个条件,然后逐个向上执行条件,直至找到满足所有条件的记录。
在 WHERE 子句中,可能会同时出现 AND 和 OR 操作符。
在这种情
况下,操作符的优先级也需要考虑。
一般来说,括号 () 的优先级最高,其次优先级是 AND,然后是 OR。
这意味着在 WHERE 子句中,如果有多个条件需要同时满足或排除,需要使用括号明确指定优先级,以避免出现意外的结果。
总之,在编写 SQL 语句时,需要注意条件执行的先后顺序和操作符
的优先级,以确保查询结果的准确性。
第1页共1页。
在 Oracle 数据库中,你可以使用BEGIN TRANSACTION或START TRANSACTION来开始一个事务,但需要注意的是,Oracle 数据库通常使用隐式事务,即每个 SQL 语句都在自己的事务中执行。
因此,在 Oracle 中显式地使用BEGIN TRANSACTION或START TRANSACTION并不是常见的做法。
如果你需要开始一个事务,并在事务中执行一系列 SQL 语句,通常使用COMMIT 提交事务或ROLLBACK回滚事务。
以下是一个简单的示例:
在这个示例中,BEGIN;表示事务的开始,然后执行了一系列 SQL 语句,最后使用COMMIT;提交事务。
如果在执行过程中发生错误或者你想回滚事务,可以使用ROLLBACK;。
需要注意的是,在 Oracle 中,默认情况下,每个 SQL 语句都是在自己的事务中执行的。
显式地使用BEGIN;和COMMIT;通常用于包装多个 SQL 语句,以确保它们在一个原子操作中执行,或者在需要进行手动事务控制的情况下使用。
ORACLE数据库SQL语句的执⾏过程 SQL语句在数据库中处理过程是怎样的呢?执⾏顺序呢?在回答这个问题前,我们先来回顾⼀下:在ORACLE数据库系统架构下,SQL 语句由⽤户进程产⽣,然后传到相对应的服务端进程,之后由服务器进程执⾏该SQL语句,如果是SELECT语句,服务器进程还需要将执⾏结果回传给⽤户进程。
SQL语句的执⾏过程⼀般如下:解析(PARSE)—— 绑定(BIND)——执⾏(EXECUTE)——提取(FETCH 只有SELECT才需要这步)解析服务器进程接收到⼀个SQL语句时,⾸先要将其转换成执⾏这个SQL语句的最有效步骤,这些步骤被称为执⾏计划。
Step 1:检查共享池中是否有之前解析相同的SQL语句后所存储的SQL⽂本、解析树和执⾏计划。
如果能从共享池的缓存库中找到之前解析过⽣成的执⾏计划,则SQL语句则不需要再次解析,便可以直接由库缓存得到之前所产⽣的执⾏计划,从⽽直接跳到绑定或执⾏阶段,这种解析称作软解析。
但是如果在共享池的库缓存中找不到对应的执⾏计划,则必须继续解析SQL、⽣成执⾏计划,这种解析称作硬解析在缓存池解析过的SQL,会有⼀个对应的哈希值与之对应,你可以通过V$SQL视图来查询,请看下⾯⼀个例⼦:SQL>SELECT*FROM SCOTT.DEPT WHERE DEPTNO =10;SQL>SELECT*FROM SCOTT.DEPT WHERE DEPTNO =20;SQL>SELECT HASH_VALUE , ADDRESS, EXECUTIONS ,SQL_TEXT2FROM V$SQL3WHERE SQL_TEXT LIKE'SELECT * FROM SCOTT.DEPT WHERE DEPTNO%'4 ;HASH_VALUE ADDRESS EXECUTIONS SQL_TEXT---------- -------- ---------- --------------------------------------------------------------------------------442836625 27EE4B7C 1SELECT*FROM SCOTT.DEPT WHERE DEPTNO =204215405494 27EEA3BC 1SELECT*FROM SCOTT.DEPT WHERE DEPTNO =10下⾯我们先清空共享池缓存的执⾏计划,然后使⽤绑定变量,查看执⾏计划的变换SQL>ALTER SYSTEM FLUSH SHARED_POOL;System alteredSQL> VARIABLE deptno NUMBER;SQL>EXECUTE :deptno :=10;PL/SQL procedure successfully completeddeptno---------10SQL>SELECT*FROM SCOTT.DEPT WHERE DEPTNO=:deptno;DEPTNO DNAME LOC------ -------------- -------------10 ACCOUNTING NEW YORKSQL>EXECUTE :deptno :=20;PL/SQL procedure successfully completeddeptno---------20SQL>SELECT*FROM SCOTT.DEPT WHERE DEPTNO=:deptno;DEPTNO DNAME LOC------ -------------- -------------20 RESEARCH DALLASSQL>SELECT HASH_VALUE , ADDRESS, EXECUTIONS ,SQL_TEXT2FROM V$SQL3WHERE SQL_TEXT LIKE' SELECT * FROM SCOTT.DEPT WHERE DEPTNO%';HASH_VALUE ADDRESS EXECUTIONS SQL_TEXT---------- -------- ---------- --------------------------------------------------------------------------------3669302979 27D2BA1C 2SELECT*FROM SCOTT.DEPT WHERE DEPTNO=:deptnoStep 2:语法分析,分析SQL语句的语法是否符合规范,衡量语句中各表达式的意义Step 3:检查是否存在语义错误和权限。
oracle sql执行原理
Oracle SQL执行原理主要包括以下几个步骤:
1. 解析SQL语句:首先,Oracle会解析SQL语句,将其转换
为内部的数据结构表示,以便后续的处理。
这包括对SQL语
法的分析,语义分析,以及生成执行计划。
2. 生成执行计划:Oracle会根据解析得到的语法树和语义信息,生成一个逻辑执行计划和一个物理执行计划。
逻辑执行计划描述了SQL语句的逻辑操作,而物理执行计划则描述了实际执
行该SQL语句时所需的具体操作。
3. 数据访问:在执行SQL语句之前,Oracle首先要获取相关
的数据。
这可以通过读取磁盘上的表数据,或者从内存中的缓存获取数据。
如果需要获取的数据不存在于缓存中,那么Oracle还会执行适当的IO操作来从磁盘读取数据。
4. 执行计划执行:一旦获取了相关的数据,Oracle就会根据物
理执行计划,执行相关的操作。
这包括对数据进行筛选,排序,连接等操作。
5. 结果返回:当执行完成后,Oracle会将执行结果返回给用户。
如果是查询语句,那么结果通常是一张表,如果是更新操作,那么返回值通常是受影响的行数。
需要注意的是,Oracle数据库还有很多优化器层面的处理,例如:动态SQL优化、动态查询变换等。
这些优化器会根据数
据库的统计信息、索引以及其他相关的信息,对执行计划进行优化,以提高执行效率。
要知道SQL语句,我想我们有必要知道SQL Server查询分析器怎么执行我们的SQL语句的,我们很多人会看执行计划,或者用Profiler来监视和调优查询语句或者存储过程慢的原因,但是如果我们知道查询分析器的执行逻辑顺序,下手的时候就胸有成竹,那么下手是不是有把握点呢?一、查询的逻辑执行顺序(1) FROM left_table(3) join_type JOIN right_table (2) ON join_condition(4) WHERE where_condition(5) GROUP BY group_by_list(6) WITH {cube | rollup}(7) HAVING having_condition(8) SELECT (9) DISTINCT (11) top_specification select_list(9) ORDER BY order_by_list标准的SQL 的解析顺序为:(1) FROM 子句组装来自不同数据源的数据(2) WHERE 子句基于指定的条件对记录进行筛选(3) GROUP BY 子句将数据划分为多个分组(4) 使用聚合函数(avg)进行计算(5) 使用HAVING子句筛选分组(6) 计算所有的表达式(7) 使用ORDER BY对结果集进行排序二、执行顺序1. FROM:对FROM子句中前两个表执行笛卡尔积生成虚拟表vt12. ON: 对vt1表应用ON筛选器只有满足join_condition 为真的行才被插入vt23. OUTER(join):如果指定了OUTER JOIN保留表(preserved table)中未找到的行将行作为外部行添加到vt2,生成t3,如果from包含两个以上表,则对上一个联结生成的结果表和下一个表重复执行步骤和步骤直接结束。
4. WHERE:对vt3应用WHERE 筛选器只有使where_condition 为true的行才被插入vt45. GROUP BY:按GROUP BY子句中的列列表对vt4中的行分组生成vt56. CUBE|ROLLUP:把超组(supergroups)插入vt6,生成vt67. HAVING:对vt6应用HAVING筛选器只有使having_condition 为true的组才插入vt78. SELECT:处理select列表产生vt89. DISTINCT:将重复的行从vt8中去除产生vt910. ORDER BY:将vt9的行按order by子句中的列列表排序生成一个游标vc1011. TOP:从vc10的开始处选择指定数量或比例的行生成vt11 并返回调用者看到这里,那么用过Linq to SQL的语法有点相似啊?如果我们我们了解了SQL Server 执行顺序,那么我们就接下来进一步养成日常SQL的好习惯,也就是在实现功能的同时有考虑性能的思想,数据库是能进行集合运算的工具,我们应该尽量的利用这个工具,所谓集合运算实际就是批量运算,就是尽量减少在客户端进行大数据量的循环操作,而用SQL语句或者存储过程代替。
ORACLE执行计划Oracle执行计划是Oracle数据库用于优化和执行SQL语句的步骤和顺序的一个计划。
在执行SQL语句之前,Oracle会分析SQL语句并生成一个执行计划,然后根据执行计划来执行SQL语句。
执行计划可以帮助开发人员和数据库管理员了解SQL语句的执行过程,找出性能瓶颈,并进行优化调整。
执行计划由一系列步骤和操作符组成,每个操作符表示一个SQL语句执行的特定步骤或操作。
Oracle数据库使用一个优化器来生成执行计划,优化器会考虑多个因素,如表的大小、索引的选择、连接类型等,以选择最佳的执行计划。
执行计划中的操作符可以分为以下几类:1. 表扫描操作符(Table Scan Operator):表示从表中逐行读取数据。
这是最基本和最常见的操作符之一、它可以是全表扫描(Full Table Scan)或索引扫描(Index Scan)。
2. 连接操作符(Join Operator):表示连接两个或多个表的操作。
连接操作是查询复杂性的一个重要组成部分,通过选择最合适的连接类型,可以极大地提高查询的性能。
3. 过滤操作符(Filter Operator):表示对查询结果进行筛选,只返回符合特定条件的数据。
过滤操作可以利用索引或表达式进行优化。
4. 排序操作符(Sort Operator):表示对查询结果进行排序,以按特定的顺序返回数据。
排序操作可以使用内存排序(In-Memory Sort)或磁盘排序(Disk Sort)。
5. 分组操作符(Group By Operator):表示将查询结果按照指定的列进行分组。
分组操作常用于聚合查询,如求和、计数等。
6. 聚合操作符(Aggregation Operator):表示对分组后的数据进行聚合计算。
聚合操作包括求和、计数、平均值等。
7. 索引操作符(Index Operator):表示使用索引来加速查询。
索引操作包括索引扫描、索引唯一扫描等。
sql语句顺序包含执⾏顺序和书写顺序
分页查询
如果⼀页记录为10条,希望查看第3页记录应该怎么查呢?
第⼀页记录起始⾏为0,⼀共查询10⾏;
第⼆页记录起始⾏为10,⼀共查询10⾏;
第三页记录起始⾏为20,⼀共查询10⾏;
8.3 分页查询
查询语句书写顺序:select – from- where- group by- having- order by-limit
查询语句执⾏顺序:from - where -group by - having - select - order by-limit
注:having与where的区别:
1.having是在分组后对数据进⾏过滤.
where是在分组前对数据进⾏过滤
2.having后⾯可以使⽤分组函数(统计函数)
where后⾯不可以使⽤分组函数。
WHERE是对分组前记录的条件,如果某⾏记录没有满⾜WHERE⼦句的条件,那么这⾏记录不会参加分组;⽽HAVING是对分组后数据的约束。
sql语句⼦句执⾏顺序
由于是⾮计算机科班出⾝,因此,缺了很多计算机⽅⾯的知识。
很多东西都是⼯作后遇到了求助度娘后才了解的,尤其是数据库这⼀块,⼀直是块⼼病。
今天看了下《SQL从⼊门到精通》,其中说到了sql各⼦句的执⾏顺序。
以前在⼀个⼤神的博客中也有看到,讲的很详细,但是由于已经找不到那个博客,今天⾃⼰将其记录下来。
了解sql各⼦句的执⾏顺序,是写出⾼质量的sql代码的基础。
各⼦句的执⾏顺序如下:
1) FROM⼦句。
2) WHERE⼦句。
3) GROUP BY⼦句。
4) HAVING⼦句。
5) SELECT⼦句。
6) ORDER BY⼦句。
SELECT 语句的各⼦句中FROM ⼦句是⾸先被执⾏的,通过FROM ⼦句获得⼀个虚拟表,然后通过WHERE ⼦句从刚才的虚拟表中获取满⾜条件的记录,⽣成新的虚拟表。
将新虚拟表中的记录通过GROUP BY ⼦句分组后得到更新的虚拟表,⽽后HAVING ⼦句在最新的虚拟表中筛选出满⾜条件的记录组成另⼀个虚拟表。
从上⼀步得到的虚拟表中,SELECT ⼦句根据select_list 将指定的列提取出来组成更新的虚拟表,最后ORDER BY ⼦句对其进⾏排序得出最终的虚拟表。
通常,⼈们将最终的虚拟表称为查询结果集。
Oracle执⾏计划顺序先从最开头⼀直往右看,直到看到最右边的并列的地⽅,对于不并列的,靠右的先执⾏:对于并列的,靠上的先执⾏。
即并列的缩进块,从上往下执⾏,⾮并列的缩进块,从下往上执⾏。
如下⽰例:Execution Plan----------------------------------------------------------0 SELECT STATEMENT Optimizer=CHOOSE1 0 NESTED LOOPS2 1 TABLE ACCESS (BY INDEX ROWID) OF 'TB_HOST_BATCH_DTL'3 2 INDEX (RANGE SCAN) OF 'XIE2TB_HOST_BATCH_DTL' (NON-UNIQUE)4 1 TABLE ACCESS (BY INDEX ROWID) OF 'TB_BATCH_TRAN_CTRL'5 4 INDEX (UNIQUE SCAN) OF 'SYS_C0034652' (UNIQUE)不妨假设最右边的数据为⾏号,语句执⾏是按块进⾏的。
从上述执⾏计划的开头⼀直往右看,直到找到最右边并列的。
也就是从SELECT STATEMENT开始往右找。
找到⼀级缩进块,只有⼀个,没有优先级可⾔,如下:1 0 NESTED LOOPS2 1 TABLE ACCESS (BY INDEX ROWID) OF 'TB_HOST_BATCH_DTL'3 2 INDEX (RANGE SCAN) OF 'XIE2TB_HOST_BATCH_DTL' (NON-UNIQUE)4 1 TABLE ACCESS (BY INDEX ROWID) OF 'TB_BATCH_TRAN_CTRL'5 4 INDEX (UNIQUE SCAN) OF 'SYS_C0034652' (UNIQUE)再在⼀级缩进块中找⼆级缩进块,找到两个,如下:第⼀个⼆级缩进块:2 1 TABLE ACCESS (BY INDEX ROWID) OF 'TB_HOST_BATCH_DTL'3 2 INDEX (RANGE SCAN) OF 'XIE2TB_HOST_BATCH_DTL' (NON-UNIQUE)第⼆个⼆级缩进块:4 1 TABLE ACCESS (BY INDEX ROWID) OF 'TB_BATCH_TRAN_CTRL'5 4 INDEX (UNIQUE SCAN) OF 'SYS_C0034652' (UNIQUE)按照并列块从上往下执⾏的原则,第⼀个⼆级缩进块的所有语句将优先于第⼆个⼆级缩进块的语句执⾏。
sql语句的执行顺序以及流程(详细掌握)程序员对sql语句的执行顺序的透彻掌握,是避免编程中各种bug和错误,歧义语句的不二法则。
1.2. SELECT DISTINCT3. FROM4. JOIN5. ON6. WHERE7. GROUP BY8. HAVING9. ORDER BY10. LIMIT如果你知道每个关键字的意思,作用,如果你还用过的话,那再好不过了。
但是,你知道这些语句,它们的执行顺序你清楚么?如果你非常清楚,你就没有必要再浪费时间继续阅读了;如果你不清楚,非常好,你应该庆幸你阅读到了这么好的一篇文章。
准备工作1. 新建一个测试数据库TestDB;2. create database TestDB;3. 创建测试表table1和table2;4. CREATE TABLE table15. (6. customer_id VARCHAR(10) NOT NULL,7. city VARCHAR(10) NOT NULL,8. PRIMARY KEY(customer_id)9. )ENGINE=INNODB DEFAULT CHARSET=UTF8;10.11. CREATE TABLE table212. (13. order_id INT NOT NULL auto_increment,14. customer_id VARCHAR(10),15. PRIMARY KEY(order_id)16. )ENGINE=INNODB DEFAULT CHARSET=UTF8;17. 插入测试数据;18. INSERT INTO table1(customer_id,city) VALUES(''163'',''hangzhou'');19. INSERT INTO table1(customer_id,city) VALUES(''9you'',''shanghai'');20. INSERT INTO table1(customer_id,city) VALUES(''tx'',''hangzhou'');21. INSERT INTO table1(customer_id,city) VALUES(''baidu'',''hangzhou'');22.23. INSERT INTO table2(customer_id) VALUES(''163'');24. INSERT INTO table2(customer_id) VALUES(''163'');25. INSERT INTO table2(customer_id) VALUES(''9you'');26. INSERT INTO table2(customer_id) VALUES(''9you'');27. INSERT INTO table2(customer_id) VALUES(''9you'');28. INSERT INTO table2(customer_id) VALUES(''tx'');29. INSERT INTO table2(customer_id) VALUES(NULL);30. 准备工作做完以后,table1和table2看起来应该像下面这样:31. mysql> select * from table1;32. +-------------+----------+33. | customer_id | city |34. +-------------+----------+35. | 163 | hangzhou |36. | 9you | shanghai |37. | baidu | hangzhou |38. | tx | hangzhou |39. +-------------+----------+40. 4 rows in set (0.00 sec)41.42. mysql> select * from table2;43. +----------+-------------+44. | order_id | customer_id |45. +----------+-------------+46. | 1 | 163 |47. | 2 | 163 |48. | 3 | 9you |49. | 4 | 9you |50. | 5 | 9you |51. | 6 | tx |52. | 7 | NULL |53. +----------+-------------+54. 7 rows in set (0.00 sec)55. 准备SQL逻辑查询测试语句56. SELECT a.customer_id, COUNT(b.order_id) as total_orders57. FROM table1 AS a58. LEFT JOIN table2 AS b59. ON a.customer_id = b.customer_id60. WHERE a.city = ''hangzhou''61. GROUP BY a.customer_id62. HAVING count(b.order_id) <>63. ORDER BY total_orders DESC;64. 使用上述SQL查询语句来获得来自杭州,并且订单数少于2的客户。
本文由我司收集整编,推荐下载,如有疑问,请与我司联系oracle sql 执行顺序12018/05/16 8 原文地址:https://wenku.baidu/view/81698889fc0a79563c1ec5da50e2524de518d08d.html 以SQL SERVER2008为例,进行说明。
先看下面这条简单SQL语句: select top10* 3from Student 4where age 20 这条SQL语句是否可以有下面两种理解呢 (1)先从Student表中选出age 20的数据,然后从这些数据中选择前面的10条数据。
(2)先从Student表中选出前10条数据,然后从这些数据中选择age 20的数据。
那么到底哪个是正确的呢?你可能会说,这还不容易,肯定是(1)是正确的。
没错,对于这样的简单的语句,一眼就能看出来,可是对于稍微复杂一些的SQL语句或者更加复杂的SQL语句,有时我们一眼就看不出来了,为了能够正确分析SQL 语句以及写出正确的SQL语句,有必要了解一下SQL语句各部分的执行顺序。
好了,我们再看下面的一条 SQL语句:select distinct top1 Table1.id,COUNT() asnameCount from Table1 innerjoin Table2 on Table1.id=Table2.id where Table1.id 4 group by Table1.id having Table1.id 3 orderby Table1.id desc 其中Table1和Table2就是我随便建立的两个非常简单的表,为了讲解方便,我也没有弄一些跟实际相结合的表,要不还要理解业务逻辑,干脆越简单越好,毕竟目的是为了说明SQL语句的执行顺序. Table1 Table2 下面先给出上面的SQL语句的执行顺序,然后进行讲解: (8)select (9)distinct (11)top1。
要知道SQL语句,我想我们有必要知道SQL Server查询分析器怎么执行我们的SQL语句的,我们很多人会看执行计划,或者用Profiler来监视和调优查询语句或者存储过程慢的原因,但是如果我们知道查询分析器的执行逻辑顺序,下手的时候就胸有成竹,那么下手是不是有把握点呢?一、查询的逻辑执行顺序(1) FROM left_table(3) join_type JOIN right_table (2) ON join_condition(4) WHERE where_condition(5) GROUP BY group_by_list(6) WITH {cube | rollup}(7) HAVING having_condition(8) SELECT (9) DISTINCT (11) top_specification select_list(9) ORDER BY order_by_list标准的SQL 的解析顺序为:(1) FROM 子句组装来自不同数据源的数据(2) WHERE 子句基于指定的条件对记录进行筛选(3) GROUP BY 子句将数据划分为多个分组(4) 使用聚合函数(avg)进行计算(5) 使用HAVING子句筛选分组(6) 计算所有的表达式(7) 使用ORDER BY对结果集进行排序二、执行顺序1. FROM:对FROM子句中前两个表执行笛卡尔积生成虚拟表vt12. ON: 对vt1表应用ON筛选器只有满足join_condition 为真的行才被插入vt23. OUTER(join):如果指定了OUTER JOIN保留表(preserved table)中未找到的行将行作为外部行添加到vt2,生成t3,如果from包含两个以上表,则对上一个联结生成的结果表和下一个表重复执行步骤和步骤直接结束。
4. WHERE:对vt3应用WHERE 筛选器只有使where_condition 为true的行才被插入vt45. GROUP BY:按GROUP BY子句中的列列表对vt4中的行分组生成vt56. CUBE|ROLLUP:把超组(supergroups)插入vt6,生成vt67. HAVING:对vt6应用HAVING筛选器只有使having_condition 为true的组才插入vt78. SELECT:处理select列表产生vt89. DISTINCT:将重复的行从vt8中去除产生vt910. ORDER BY:将vt9的行按order by子句中的列列表排序生成一个游标vc1011. TOP:从vc10的开始处选择指定数量或比例的行生成vt11 并返回调用者看到这里,那么用过Linq to SQL的语法有点相似啊?如果我们我们了解了SQL Server 执行顺序,那么我们就接下来进一步养成日常SQL的好习惯,也就是在实现功能的同时有考虑性能的思想,数据库是能进行集合运算的工具,我们应该尽量的利用这个工具,所谓集合运算实际就是批量运算,就是尽量减少在客户端进行大数据量的循环操作,而用SQL语句或者存储过程代替。
三、只返回需要的数据返回数据到客户端至少需要数据库提取数据、网络传输数据、客户端接收数据以及客户端处理数据等环节,如果返回不需要的数据,就会增加服务器、网络和客户端的无效劳动,其害处是显而易见的,避免这类事件需要注意:A、横向来看(1) 不要写SELECT * 的语句,而是选择你需要的字段。
(2) 当在SQL语句中连接多个表时, 请使用表的别名并把别名前缀于每个Column上。
这样一来,就可以减少解析的时间并减少那些由Column歧义引起的语法错误。
1如有表table1(ID,col1)和table2(ID,col2)1Select A.ID, A.col1, B.col22-- Select A.ID, col1, col2 –不要这么写,不利于将来程序扩展3from table1 A inner join table2 B on A.ID=B.ID Where …B、纵向来看(1) 合理写WHERE子句,不要写没有WHERE的SQL语句。
(2) SELECT TOP N * -- 没有WHERE条件的用此替代。
四、尽量少做重复的工作A、控制同一语句的多次执行,特别是一些基础数据的多次执行是很多程序员很少注意的。
B、减少多次的数据转换,也许需要数据转换是设计的问题,但是减少次数是程序员可以做到的。
C、杜绝不必要的子查询和连接表,子查询在执行计划一般解释成外连接,多余的连接表带来额外的开销。
D、合并对同一表同一条件的多次UPDATE,比如UPDATE EMPLOYEE SET FNAME='HAIWER'WHERE EMP_ID=' VPA30890F'UPDATE EMPLOYEE SET LNAME='YANG'WHERE EMP_ID=' VPA30890F'这两个语句应该合并成以下一个语句UPDATE EMPLOYEE SET FNAME='HAIWER',LNAME='YANG'WHERE EMP_ID='VPA30890F'E、UPDATE操作不要拆成DELETE操作+INSERT操作的形式,虽然功能相同,但是性能差别是很大的。
五、注意临时表和表变量的用在复杂系统中,临时表和表变量很难避免,关于临时表和表变量的用法,需要注意:A、如果语句很复杂,连接太多,可以考虑用临时表和表变量分步完成。
B、如果需要多次用到一个大表的同一部分数据,考虑用临时表和表变量暂存这部分数据。
C、如果需要综合多个表的数据,形成一个结果,可以考虑用临时表和表变量分步汇总这多个表的数据。
D、其他情况下,应该控制临时表和表变量的使用。
E、关于临时表和表变量的选择,很多说法是表变量在内存,速度快,应该首选表变量,但是在实际使用中发现:(1) 主要考虑需要放在临时表的数据量,在数据量较多的情况下,临时表的速度反而更快。
(2) 执行时间段与预计执行时间(多长)F、关于临时表产生使用SELECT INTO和CREATE TABLE + INSERT INTO的选择,一般情况下:SELECT INTO会比CREATE TABLE + INSERT INTO的方法快很多,但是SELECT INTO会锁定TEMPDB的系统表SYSOBJECTS、SYSINDEXES、SYSCOLUMNS,在多用户并发环境下,容易阻塞其他进程。
所以我的建议是,在并发系统中,尽量使用CREATE TABLE + INSERT INTO,而大数据量的单个语句使用中,使用SELECT INTO。
六、子查询的用法子查询是一个SELECT 查询,它嵌套在SELECT、INSERT、UPDATE、DELETE 语句或其它子查询中。
任何允许使用表达式的地方都可以使用子查询,子查询可以使我们的编程灵活多样,可以用来实现一些特殊的功能。
但是在性能上,往往一个不合适的子查询用法会形成一个性能瓶颈。
如果子查询的条件中使用了其外层的表的字段,这种子查询就叫作相关子查询。
相关子查询可以用IN、NOT IN、EXISTS、NOT EXISTS引入。
关于相关子查询,应该注意:(1) NOT IN、NOT EXISTS的相关子查询可以改用LEFT JOIN代替写法。
比如:SELECT PUB_NAME FROM PUBLISHERS WHERE PUB_ID NOTIN (SELECT PUB_ID FROM TITLES WHERE TYPE ='BUSINESS')可以改写成:SELECT A.PUB_NAME FROM PUBLISHERS A LEFTJOIN TITLES B ON B.TYPE='BUSINESS'AND A.PUB_ID=B. PUB_ID WHERE B.PUB_ID IS NULL比如NOT EXISTS:SELECT TITLE FROM TITLESWHERE NOT EXISTS(SELECT TITLE_ID FROM SALES WHERE TITLE_ID = TITLES.TITLE_ID)1可以改写成:SELECT TITLEFROM TITLES LEFTJOIN SALESON SALES.TITLE_ID = TITLES.TITLE_IDWHERE SALES.TITLE_ID ISNULL2)如果保证子查询没有重复,IN、EXISTS的相关子查询可以用INNER JOIN 代替。
比如:SELECT PUB_NAMEFROM PUBLISHERSWHERE PUB_ID IN(SELECT PUB_IDFROM TITLESWHERE TYPE ='BUSINESS')1可以改写成:SELECT A.PUB_NAME --SELECT DISTINCT A.PUB_NAMEFROM PUBLISHERS A INNERJOIN TITLES BON B.TYPE ='BUSINESS'ANDA.PUB_ID=B. PUB_ID(3) IN的相关子查询用EXISTS代替,比如:SELECT PUB_NAME FROM PUBLISHERSWHERE PUB_ID IN(SELECT PUB_ID FROM TITLES WHERE TYPE ='BUSINESS')可以用下面语句代替:SELECT PUB_NAME FROM PUBLISHERS WHERE EXISTS(SELECT1FROM TITLES WHERE TYPE ='BUSINESS'ANDPUB_ID= PUBLISHERS.PUB_ID)4)不要用COUNT(*)的子查询判断是否存在记录,最好用LEFT JOIN或者EXISTS,比如有人写这样的语句:SELECT JOB_DESC FROM JOBSWHERE (SELECTCOUNT(*) FROM EMPLOYEE WHERE JOB_ID=JOBS.JOB_ID)=0 应该改成:SELECT JOBS.JOB_DESC FROM JOBS LEFTJOIN EMPLOYEEON EMPLOYEE.JOB_ID=JOBS.JOB_IDWHERE EMPLOYEE.EMP_ID ISNULLSELECT JOB_DESC FROM JOBSWHERE (SELECT COUNT(*) FROM EMPLOYEE WHERE JOB_ID=JOBS.JOB_ID)0 应该改成:SELECT JOB_DESC FROM JOBSWHEREEXISTS (SELECT 1 FROM EMPLOYEE WHERE JOB_ID=JOBS.JOB_ID) 七:尽量使用索引建立索引后,并不是每个查询都会使用索引,在使用索引的情况下,索引的使用效率也会有很大的差别。