
软件设计与开发
Oracle专题———外连接过滤
黄庆华
(中油辽宁沈阳销售分公司信息中心辽宁沈阳110041)
教事技术与表用
摘要:在ANSISQL-92标准的SQL中,外连接分为left outer join在外连接,right outer join右外连接fullouter join全外连接,在oracle9i之前用(+)支持。从oracle9i之后,既可以使用原有的(+)外连接符合,电可以使用ANSISQL一92标准的外连接
在使用外连接的时候,用where于句和and条件去做过滤限制的时领,需要注意语句的逐辑是否符合我们的预期。关键调:外连接
中图分类号:TP311.1
文献标识码:A
1、ANSISQL-92标准外连接
1.1用where条件去限制
文章编号:1007-9416(2011)08-0130-02
SQL> SELECT EMPNO,A.DEPTNO,B.DEPTNO,B. DNAME
在这种情况下,oracle会按照连接条件去做连接,对于不符合过滤条件的记录,直接过滤掉。当然,oracle优化器再处理这种情况的时候,在不改变sql功能的情况下,可能会在连接前先应用where 条件过滤一些数据,以此来提高sqi效率。
SQL> INSERT INTO DEPT (DEPTNO,DNAME) VAL UES (99,'test'),
SQL> COMMIT
SQL> SELECT EMPNO,A.DEPTNO,B.DEPTNO,B. DNAME
FROM EMP A
LEFT JOIN DEPT B
ON A.DEPTNO = B.DEPTNO WHERE B.DEPTNO = 99;
EMPNODEPTNODEPTNODNAME
如果把上面sql的where子句改为对A表的限制,即wherea, deptno=99,仍查询不到结果,通过执行计划可以看到,oracle首先通过索引访间dept,并且限制了条件b.deptno=99,然后对emp表做全表扫描,也就是先应用where条件,然后再去做表与表的关联操作.这样看来,如果过滤条件放在where子句中,是不是oracle 就是先应用where过滤,然后再做连接操作,是不是完全这样的呢?再看下面的这个例子:
SQL> SELECT A.DEPTNO, A.DNAME, B.EMPNO, B.ENAME
FROM DEPT A
LEFT JOIN EMP B
ON A.DEPTNO = B.DEPTNO WHERE B.DEPTNO IS NULL
DEPTNO DNAME
EMPNO ENAME
99 test
这个sgl的执行计划清楚的表明,oracle是先把A,B表的记录都取出来,然后做连接,最后才去filter过滤。可以看到,用 where去限制的话,oracle可能先过滤再连接,也有可能先连接再过滤。
1.2用and条件去限制
把where子句的b,deptno=99改为join中的and-deptno=99
130 月方数据
b
FROM EMP A
LEFT JOIN DEPT B
ON A.DEPTNO = B.DEPTNO AND B.DEPTNO = 99;
EMPNO DEPTNO DEPTNO DNAME
7370 7369 7499
20 20 30
再来看看对A表的deptno做限制:
SQL> SELECT EMPNO,A.DEPTNO, B.DEPTNO, B. DNAME
FROM EMP A
LEFT JOIN DEPT B
ON A.DEPTNO = B.DEPTNO AND A.DEPTNO =10;
EMPNODEPTNODEPTNODNAME
7566 7654 7698* 7782
20 30 30
10
10ACCOUNTING
可以看到,在访间A表的时候并没有用过滤条件,取出的总的纪录数还是和A表纪录数一致,其实,当deptno的过滤条件放在join 子句旬中的时候,b.deptno"条件为任何值,结果都会出所有纪录,因为此时相当于告诉oracle,我要先对A表全表扫描方式访间A表所有纪录,然后再去和B表做左关联,关联上的话,就把从表对应字段的值填上,关联不上的就置空值。3rightjoinrightjoin的情况和leftjoin类似。
1.3总结
当在内连接查询中加人条件时,无论是将它加人到join子句,还是加入到where子句,其效果是完全-样的,但对于外连接情况就不间了,总结如下,(1)当把条件加人到join子句时, oracle首先对相关表进行连接,然后再对连接结果做过滤操作,符合条件的纪录会返回完整的记录结果,不符合过滤条件的,从表相应的字段置为空,总之,SQ1出来的纪录数肯定是和连接结果集的纪录数一致。(2)如果将条件放到where子句中,