举例证明Oracle语句的执行顺序

惯例先上oracle数据库版本信息:

SQL> select * from v$version;

BANNER
----------------------------------------------------------------
Oracle9i Enterprise Edition Release 9.2.0.1.0 - Production
PL/SQL Release 9.2.0.1.0 - Production
CORE    9.2.0.1.0       Production
TNS for 32-bit Windows: Version 9.2.0.1.0 - Production
NLSRTL Version 9.2.0.1.0 - Production

       Oracle数据库一直在更新,具体版本不同,Oracle可能会产生一些小的变动,所以下面的测试案例全部都是在我的Oracle 9i版本上测试成功的,在9i以上版本不确定,如有不同,欢迎评论补充!!!

众所周知,Oracle数据库执行一条SQL语句的顺序是:

1.语法分析,这阶段主要是判断有没语法错误,比如常见的拼写错误以及逻辑错误,比如:select少写个e变成slect,这个就是在语法分析阶段检查出来的

2.语义分析,这阶段主要是检查SQL语句中访问的对象是否存在以及该用户是否具备相应的权限,比如:select * from TEST;如果数据库中没有表TEST或者该用户没有权限访问该表,这个就是在语义分析阶段检查出来的

3.对SQL语句进行解析,利用内部算法进行解析,生成解析数以及执行计划

4.执行SQL语句,返回执行结果

首先从语法分析阶段入手,语法分析阶段是从右往左进行的,下面举个简单的例子来证明一下:

SQL> select * from emp where 1/0=1 and 1 = 2;

未选定行

SQL> select * from emp where 1 = 2 and 1/0=1;
select * from emp where 1 = 2 and 1/0=1
                                   *
ERROR 位于第 1 行:
ORA-01476: 除数为 0

       简要分析一下:第一个SQL语句之所以返回“未选定行”,是因为执行这个SQL语句时从右往左进行,先判断1 = 2这个显而易见的不成立,而逻辑判断符是and,所以直接忽略前面的条件:1/0=1,条件不成立直接返回“未选定行”;

       而第二个SQL语句为什么报错呢?同理是因为他从右往左进行语法分析,先判断1/0=1这个条件,显然0不能作为除数,所以直接报错:ORA-01476:除数为0;

       显然,这个例子证明了语法分析阶段是从右往左进行的,如果是从左往右进行,那么返回的结果应该是第一句SQL语句返回ORA-01476:除数为0,第二句返回“未选定行”。

       语义分析阶段主要检查SQL语句中访问的对象是否存在以及该用户是否具备相应的权限,实在想不出啥比较好的例子能够证明语义分析阶段的执行顺序,暂且跳过。

       接下来分析一下SQL语句执行时where字句的执行顺序:

SQL> desc test;
 名称                                      是否为空? 类型
 ----------------------------------------- -------- ----------------------------
 T1                                                 VARCHAR2(10)
 T2                                                 VARCHAR2(10)
SQL> select * from test;

T1         T2
---------- ----------
hl         abc
yy         1
yy         2
SQL> select * from test where to_number(t2) > 1 and t1 = 'yy';

T1         T2
---------- ----------
yy         2

SQL> select * from test where t1 = 'yy' and to_number(t2) > 1;
select * from test where t1 = 'yy' and to_number(t2) > 1
                                       *
ERROR 位于第 1 行:
ORA-01722: 无效数字
简要解释一下同样的筛选条件,不同的顺序,执行结果却完全不同的原因:

        首先第一个没有报错的SQL语句为什么正确而且有结果呢?其实是因为where语句是自下而上执行,从右往左执行,依据这个顺序,首先通过t1 = 'yy'过滤掉第一行记录,只剩yy----1和yy----2这两行记录,然后通过to_number(t2) > 1这个条件过滤掉yy----1这行记录,所以返回结果如上。

        再来看看为什么第二行会报错呢?同样还是因为where字句的执行顺序造成的。首先先判断条件:to_number(t2) > 1,先对Test这个表进行全表扫描,由于第一条记录是:hl----abc,显然abc不可能通过to_number()强制转化成数字,所以直接报错了。

        如果觉得这个例子还不能让你信服,再来看看下面的例子:

create or replace function f1 (v_in_name varchar2)
return varchar2
as
begin
dbms_output.put_line ('f1的v_in_name:'||v_in_name);
return v_in_name;
exception
when no_data_found then
dbms_output.put_line ('出现异常');
end;
/
create or replace function f2 (v_in_name varchar2)
return varchar2
as
begin
dbms_output.put_line ('f2的v_in_name:'||v_in_name);
return v_in_name;
exception
when no_data_found then
dbms_output.put_line ('出现异常');
end;
/
select 1 from dual where f1('1')=1 and f2('1')=1;
select 1 from dual where f2('1')=1 and f1('1')=1;
通过执行这俩SQL语句的输出结果可以判断出where字句确实是从右往左执行的。(我电脑oracle版本是9i,版本较低,无法贴出输出结果,但我在同学10g版本上测试过,执行第一个SQL语句先输出f2的v_in_name:1然后再输出f1,第二个与之相反)。


欢迎关注行者摩罗微信公众号(xingzhemoluo),共同交流编程经验,扫描下方二维码即可;




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值