oracle sql语句执行顺序

合集下载

Oraclesql语句执行顺序

Oraclesql语句执行顺序

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查询语句的步骤

Oracle执行SQL查询语句的步骤

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语句执行流程与顺序原理解析

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语句执行原理和完整过程详解

oracle-SQL语句执行原理和完整过程详解

oracle-SQL语句执行原理和完整过程详解SQL 语句执行过程详解一条 sql,plsql 的执行到底是怎样执行的呢?一、SQL 语句执行原理:第一步:客户端把语句发给服务器端执行当我们在客户端执行select 语句时,客户端会把这条SQL 语句发送给服务器端,让服务器端的进程来处理这语句。

也就是说,Oracle 客户端是不会做任何的操作,他的主要任务就是把客户端产生的一些 SQL 语句发送给服务器端。

虽然在客户端也有一个数据库进程,但是,这个进程的作用跟服务器上的进程作用事不相同的。

服务器上的数据库进程才会对SQL 语句进行相关的处理。

不过,有个问题需要说明,就是客户端的进程跟服务器的进程是一一对应的。

也就是说,在客户端连接上服务器后,在客户端与服务器端都会形成一个进程,客户端上的我们叫做客户端进程;而服务器上的我们叫做服务器进程。

第二步:语句解析当客户端把 SQL 语句传送到服务器后,服务器进程会对该语句进行解析。

同理,这个解析的工作, 也是在服务器端所进行的。

虽然这只是一个解析的动作,但是,其会做很多“小动作”。

1. 查询高速缓存(library cache)。

服务器进程在接到客户端传送过来的SQL 语句时,不会直接去数据库查询。

而是会先在数据库的高速缓存中去查找,是否存在相同语句的执行计划。

如果在数据高速缓存中,则服务器进程就会直接执行这个SQL 语句,省去后续的工作。

所以,采用高速数据缓存的话,可以提高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 条件的先后顺序

sql 条件的先后顺序

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 开始事务的sql语句

oracle 开始事务的sql语句

在 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语句的处理过程

Oracle之SQL语句的处理过程
EXEC SQL UPDATE employees SET salary = 1.10 * salary WHERE department_id = :var_department_id;
• var_department_id是程序变量,里面包含部门号(我们 要修改该部门的职员的工资)。
• 当这个SQL语句执行时,使 创建游标(Create a Cursor) • 由程序接口调用创建一个游标(cursor)。任何SQL语 句都会创建它,特别在运行DML语句时,都是自动创 建游标的,不需要开发人员干预。多数应用中,游标的 创建是自动的。然而,在预编译程序(pro*c)中游标的 创建,可能是隐含的,也可能显式的创建。在存储过程 中也是这样的。
* 以上任何一步出错误,都将导致语句报错,中止执行。
以上语句处理步骤解释
—7 —
• 只有在共享池中不存在等价SQL语句的情况下,才对SQL语句作语法分析。在这种 情况下,数据库内核重新为该语句分配新的共享SQL区,并对语句进行语法分析。 进行语法分析需要耗费较多的资源,所以要尽量避免进行语法分析,这是优化的技 巧之一。
—8 —
查询与其它类型的SQL语句不同,因为在成功执行后作为结果将返回数据。
第3步: 描述查询结果(Describe Results of a Query) 描述阶段只有在查询结果的各个列是未知时才需要;例如,当查询由用 户交互地输入需要输出的列名。在这种情况要用描述阶段来决定查询结 果的特征(数据类型,长度和名字)。
DML 语句的处理
• 每种类型的语句都需要如下阶段:
• 第1步: Create a Cursor 创建游标 • 第2步: Parse the Statement 分析语句 • 第5步: Bind Any Variables 绑定变量 • 第7步: Run the Statement 运行语句 • 第9步: Close the Cursor 关闭游标
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

要知道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) 七:尽量使用索引建立索引后,并不是每个查询都会使用索引,在使用索引的情况下,索引的使用效率也会有很大的差别。

相关文档
最新文档