[20200711]关于左右连接的问题.txt --//以前写的,链接如下:http://blog.itpub.net/267265/viewspace-1593068/ --//仅仅做一些必要的补充.我个人的工作习惯使用(+)方式 1.环境: SCOTT@test01p> @ ver1 PORT_STRING VERSION BANNER CON_ID ------------------------------ -------------- -------------------------------------------------------------------------------- ---------- IBMPC/WIN_NT64-9.1.0 12.2.0.1.0 Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production 0 create table t1 as select rownum id,rownum ||'t1' data from dual connect by level<=3; create table t2 as select rownum+1 id,(rownum+1)||'t2' data from dual connect by level<=3; --//分析略. SCOTT@test01p> select * from t1; ID DATA --- ----- 1 1t1 2 2t1 3 3t1 SCOTT@test01p> select * from t2; ID DATA --- ----- 2 2t2 3 3t2 4 4t2 2.测试: SCOTT@test01p> set null NULL SCOTT@test01p> select * from t1 left join t2 on t1.id=t2.id ; ID DATA ID DATA --- ----- ---------- ----- 2 2t1 2 2t2 3 3t1 3 3t2 1 1t1 NULL NULL --//left join 相当于在右边写入(+),等效的写法是select * from t1 ,t2 where t1.id=t2.id(+) ; --//我个人更加喜欢(+)的写法.但是如果如下语句: SCOTT@test01p> select * from t1 left join t2 on t1.id=t2.id and t1.id=2; ID DATA ID DATA --- ----- ---------- ------ 2 2t1 2 2t2 1 1t1 NULL NULL 3 3t1 NULL NULL SCOTT@test01p> @ dpc '' '' PLAN_TABLE_OUTPUT ------------------------------------- SQL_ID 5katgcygcphpc, child number 0 ------------------------------------- select * from t1 left join t2 on t1.id=t2.id and t1.id=2 Plan hash value: 1823443478 ------------------------------------------------------------------------------------------------------- | Id | Operation | Name | E-Rows |E-Bytes| Cost (%CPU)| E-Time | OMem | 1Mem | Used-Mem | ------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | | | 6 (100)| | | | | |* 1 | HASH JOIN OUTER | | 3 | 42 | 6 (0)| 00:00:01 | 1743K| 1743K| 823K (0)| | 2 | TABLE ACCESS FULL| T1 | 3 | 21 | 3 (0)| 00:00:01 | | | | | 3 | TABLE ACCESS FULL| T2 | 3 | 21 | 3 (0)| 00:00:01 | | | | ------------------------------------------------------------------------------------------------------- Query Block Name / Object Alias (identified by operation id): ------------------------------------------------------------- 1 - SEL$2BFA4EE4 2 - SEL$2BFA4EE4 / T1@SEL$1 3 - SEL$2BFA4EE4 / T2@SEL$1 Predicate Information (identified by operation id): --------------------------------------------------- 1 - access("T1"."ID"="T2"."ID" AND "T1"."ID"=CASE WHEN ("T2"."ID" IS NOT NULL) THEN 2 ELSE 2 END ) Note ----- - Warning: basic plan statistics not available. These are only collected when: * hint 'gather_plan_statistics' is used for the statement or * parameter 'statistics_level' is set to 'ALL', at session or system level --//注意看Predicate Information (identified by operation id):,acces是: 1 - access("T1"."ID"="T2"."ID" AND "T1"."ID"=CASE WHEN ("T2"."ID" IS NOT NULL) THEN 2 ELSE 2 END ) --//转换的sql语句查询条件发生了变化,以前我一直认为很难有开发写出这样的sql语句. SCOTT@test01p> @ expand_sql_text12c.sql 5katgcygcphpc old 4: select sql_fulltext into m_sql_in from v$sqlarea where sql_id='&&1'; new 4: select sql_fulltext into m_sql_in from v$sqlarea where sql_id='5katgcygcphpc'; PL/SQL procedure successfully completed. M_SQL_OUT ---------------------------------------------------------------------------------------------------------------------------------------------------------------- SELECT "A1"."QCSJ_C000000000300000_0" "QCSJ_C000000000300000","A1"."QCSJ_C000000000300002_1" "QCSJ_C000000000300002","A1"."QCSJ_C000000000300001_2" "QCSJ_C00000 0000300001","A1"."QCSJ_C000000000300003_3" "QCSJ_C000000000300003" FROM (SELECT "A3"."ID" "QCSJ_C000000000300000_0","A3"."DATA" "QCSJ_C000000000300002_1","A2". "ID" "QCSJ_C000000000300001_2","A2"."DATA" "QCSJ_C000000000300003_3" FROM "SCOTT"."T1" "A3","SCOTT"."T2" "A2" WHERE "A3"."ID"="A2"."ID" AND "A3"."ID"=2) "A1" --//格式话如下: SELECT "A1"."QCSJ_C000000000300000_0" "QCSJ_C000000000300000", "A1"."QCSJ_C000000000300002_1" "QCSJ_C000000000300002", "A1"."QCSJ_C000000000300001_2" "QCSJ_C000000000300001", "A1"."QCSJ_C000000000300003_3" "QCSJ_C000000000300003" FROM (SELECT "A3"."ID" "QCSJ_C000000000300000_0", "A3"."DATA" "QCSJ_C000000000300002_1","A2"."ID" "QCSJ_C000000000300001_2", "A2"."DATA" "QCSJ_C000000000300003_3" FROM "SCOTT"."T1" "A3", "SCOTT"."T2" "A2" WHERE "A3"."ID" = "A2"."ID" AND "A3"."ID"=2) "A1" --//明显看出这样的执行计划取消了外连接,根本不对,expand出了问题.不知道是否是bug.换另外的方式看看: SCOTT@test01p> @ 10053x 5katgcygcphpc 0 PL/SQL procedure successfully completed. --//检查转储发现,注:sql语句我做了格式化处理. Final query after transformations:******* UNPARSED QUERY IS ******* SELECT "T1"."ID" "ID","T1"."DATA" "DATA","T2"."ID" "ID", "T2"."DATA" "DATA" FROM "SCOTT"."T1" "T1","SCOTT"."T2" "T2" WHERE "T1"."ID" = "T2"."ID"(+) AND "T1"."ID" = CASE WHEN ("T2"."ID"(+) IS NOT NULL) THEN 2 ELSE 2 END kkoqbc: optimizing query block SEL$2BFA4EE4 (#0) 3.换成加号的写法: --//前面的转化不做测试了. SCOTT@test01p> select * from t1,t2 where t1.id=t2.id(+) and t1.id(+)=2; ID DATA ID DATA --- ---- --- ------ 2 2t1 2 2t2 --//结果不对.因为连接在t2表存在(+).使用t1.id(+)=2相当于没有加号,变成t1.id=2;改写如下: SCOTT@test01p> select * from t1,t2 where t1.id=t2.id(+) and t2.id(+)=2; ID DATA ID DATA --- ----- ---------- ------------ 2 2t1 2 2t2 1 1t1 NULL NULL 3 3t1 NULL NULL --//OK现在正确了.换一句话讲上面的语句写成如下: SCOTT@test01p> select * from t1 left join t2 on t1.id=t2.id and t2.id=2; ID DATA ID DATA --- ----- ---------- ---------- 2 2t1 2 2t2 1 1t1 NULL NULL 3 3t1 NULL NULL SCOTT@test01p> @ dpc '' '' PLAN_TABLE_OUTPUT ------------------------------------- SQL_ID bzjahpxh02m63, child number 0 ------------------------------------- select * from t1 left join t2 on t1.id=t2.id and t2.id=2 Plan hash value: 1823443478 ------------------------------------------------------------------------------------------------------- | Id | Operation | Name | E-Rows |E-Bytes| Cost (%CPU)| E-Time | OMem | 1Mem | Used-Mem | ------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | | | 6 (100)| | | | | |* 1 | HASH JOIN OUTER | | 3 | 42 | 6 (0)| 00:00:01 | 1995K| 1995K| 978K (0)| | 2 | TABLE ACCESS FULL| T1 | 3 | 21 | 3 (0)| 00:00:01 | | | | |* 3 | TABLE ACCESS FULL| T2 | 1 | 7 | 3 (0)| 00:00:01 | | | | ------------------------------------------------------------------------------------------------------- Query Block Name / Object Alias (identified by operation id): ------------------------------------------------------------- 1 - SEL$2BFA4EE4 2 - SEL$2BFA4EE4 / T1@SEL$1 3 - SEL$2BFA4EE4 / T2@SEL$1 Predicate Information (identified by operation id): --------------------------------------------------- 1 - access("T1"."ID"="T2"."ID") 3 - filter("T2"."ID"=2) SCOTT@test01p> @ expand_sql_text12c.sql bzjahpxh02m63 0 PL/SQL procedure successfully completed. M_SQL_OUT ---------------------------------------------------------------------------------------------------------------------------------------------------------------- SELECT "A1"."QCSJ_C000000000300000_0" "QCSJ_C000000000300000","A1"."QCSJ_C000000000300002_1" "QCSJ_C000000000300002","A1"."QCSJ_C000000000300001_2" "QCSJ_C00000 0000300001","A1"."QCSJ_C000000000300003_3" "QCSJ_C000000000300003" FROM (SELECT "A3"."ID" "QCSJ_C000000000300000_0","A3"."DATA" "QCSJ_C000000000300002_1","A2". "ID" "QCSJ_C000000000300001_2","A2"."DATA" "QCSJ_C000000000300003_3" FROM "SCOTT"."T1" "A3","SCOTT"."T2" "A2" WHERE "A3"."ID"="A2"."ID" AND "A2"."ID"=2) "A1" --//转换依旧是错的. SCOTT@test01p> @ 10053x bzjahpxh02m63 0 PL/SQL procedure successfully completed. --//检查转储发现,注:sql语句我做了格式化处理. Final query after transformations:******* UNPARSED QUERY IS ******* SELECT "T1"."ID" "ID","T1"."DATA" "DATA","T2"."ID" "ID", "T2"."DATA" "DATA" FROM "SCOTT"."T1" "T1","SCOTT"."T2" "T2" WHERE "T1"."ID" = "T2"."ID"(+) AND "T2"."ID"(+) = 2 kkoqbc: optimizing query block SEL$2BFA4EE4 (#0) --//也就是讲使用ansi语法,这样写不会发生像前面的转换. 4.继续测试: SCOTT@test01p> select * from t1 left join t2 on t1.id=t2.id and t1.data='2t1'; ID DATA ID DATA --- ----- ---------- ------ 2 2t1 2 2t2 1 1t1 null null 3 3t1 null null SCOTT@test01p> @ dpc '' '' PLAN_TABLE_OUTPUT ------------------------------------- SQL_ID 5w608wztt55qp, child number 0 ------------------------------------- select * from t1 left join t2 on t1.id=t2.id and t1.data='2t1' Plan hash value: 1823443478 ------------------------------------------------------------------------------------------------------- | Id | Operation | Name | E-Rows |E-Bytes| Cost (%CPU)| E-Time | OMem | 1Mem | Used-Mem | ------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | | | 6 (100)| | | | | |* 1 | HASH JOIN OUTER | | 3 | 42 | 6 (0)| 00:00:01 | 1995K| 1995K| 982K (0)| | 2 | TABLE ACCESS FULL| T1 | 3 | 21 | 3 (0)| 00:00:01 | | | | | 3 | TABLE ACCESS FULL| T2 | 3 | 21 | 3 (0)| 00:00:01 | | | | ------------------------------------------------------------------------------------------------------- Query Block Name / Object Alias (identified by operation id): ------------------------------------------------------------- 1 - SEL$2BFA4EE4 2 - SEL$2BFA4EE4 / T1@SEL$1 3 - SEL$2BFA4EE4 / T2@SEL$1 Predicate Information (identified by operation id): --------------------------------------------------- 1 - access("T1"."ID"="T2"."ID" AND "T1"."DATA"=CASE WHEN ("T2"."ID" IS NOT NULL) THEN '2t1' ELSE '2t1' END ) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Note ----- - Warning: basic plan statistics not available. These are only collected when: * hint 'gather_plan_statistics' is used for the statement or * parameter 'statistics_level' is set to 'ALL', at session or system level --//如果写成如上,写成(+)的语法就比较复杂. SCOTT@test01p> select * from t1 left join t2 on t1.id=t2.id and t2.data='2t2'; ID DATA ID DATA --- ----- ---------- ------- 2 2t1 2 2t2 1 1t1 null null 3 3t1 null null SCOTT@test01p> @ dpc '' '' PLAN_TABLE_OUTPUT ------------------------------------- SQL_ID b4xnzyw0sgp11, child number 0 ------------------------------------- select * from t1 left join t2 on t1.id=t2.id and t2.data='2t2' Plan hash value: 1823443478 ------------------------------------------------------------------------------------------------------- | Id | Operation | Name | E-Rows |E-Bytes| Cost (%CPU)| E-Time | OMem | 1Mem | Used-Mem | ------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | | | 6 (100)| | | | | |* 1 | HASH JOIN OUTER | | 3 | 42 | 6 (0)| 00:00:01 | 1995K| 1995K| 972K (0)| | 2 | TABLE ACCESS FULL| T1 | 3 | 21 | 3 (0)| 00:00:01 | | | | |* 3 | TABLE ACCESS FULL| T2 | 1 | 7 | 3 (0)| 00:00:01 | | | | ------------------------------------------------------------------------------------------------------- Query Block Name / Object Alias (identified by operation id): ------------------------------------------------------------- 1 - SEL$2BFA4EE4 2 - SEL$2BFA4EE4 / T1@SEL$1 3 - SEL$2BFA4EE4 / T2@SEL$1 Predicate Information (identified by operation id): --------------------------------------------------- 1 - access("T1"."ID"="T2"."ID") 3 - filter("T2"."DATA"='2t2') 5.right join测试看看: SCOTT@test01p> select * from t1 right join t2 on t1.id=t2.id and t2.id=2; ID DATA ID DATA ---------- --------- ----- 2 2t1 2 2t2 null null 4 4t2 null null 3 3t2 SCOTT@test01p> @ dpc '' '' PLAN_TABLE_OUTPUT ------------------------------------- SQL_ID 79u9x9fb2rq37, child number 0 ------------------------------------- select * from t1 right join t2 on t1.id=t2.id and t2.id=2 Plan hash value: 1426054487 ------------------------------------------------------------------------------------------------------- | Id | Operation | Name | E-Rows |E-Bytes| Cost (%CPU)| E-Time | OMem | 1Mem | Used-Mem | ------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | | | 6 (100)| | | | | |* 1 | HASH JOIN OUTER | | 3 | 42 | 6 (0)| 00:00:01 | 1743K| 1743K| 943K (0)| | 2 | TABLE ACCESS FULL| T2 | 3 | 21 | 3 (0)| 00:00:01 | | | | | 3 | TABLE ACCESS FULL| T1 | 3 | 21 | 3 (0)| 00:00:01 | | | | ------------------------------------------------------------------------------------------------------- Query Block Name / Object Alias (identified by operation id): ------------------------------------------------------------- 1 - SEL$2BFA4EE4 2 - SEL$2BFA4EE4 / T2@SEL$1 3 - SEL$2BFA4EE4 / T1@SEL$1 Predicate Information (identified by operation id): --------------------------------------------------- 1 - access("T1"."ID"="T2"."ID" AND "T2"."ID"=CASE WHEN ("T1"."ID" IS NOT NULL) THEN 2 ELSE 2 END ) SCOTT@test01p> select * from t1 right join t2 on t1.id=t2.id and t1.id=2; ID DATA ID DATA ---------- ----- --- ------ 2 2t1 2 2t2 null null 4 4t2 null null 3 3t2 SCOTT@test01p> @ dpc '' '' PLAN_TABLE_OUTPUT ------------------------------------- SQL_ID fz7yxaqccfb6z, child number 0 ------------------------------------- select * from t1 right join t2 on t1.id=t2.id and t1.id=2 Plan hash value: 1426054487 ------------------------------------------------------------------------------------------------------- | Id | Operation | Name | E-Rows |E-Bytes| Cost (%CPU)| E-Time | OMem | 1Mem | Used-Mem | ------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | | | 6 (100)| | | | | |* 1 | HASH JOIN OUTER | | 3 | 42 | 6 (0)| 00:00:01 | 1995K| 1995K| 955K (0)| | 2 | TABLE ACCESS FULL| T2 | 3 | 21 | 3 (0)| 00:00:01 | | | | |* 3 | TABLE ACCESS FULL| T1 | 1 | 7 | 3 (0)| 00:00:01 | | | | ------------------------------------------------------------------------------------------------------- Query Block Name / Object Alias (identified by operation id): ------------------------------------------------------------- 1 - SEL$2BFA4EE4 2 - SEL$2BFA4EE4 / T2@SEL$1 3 - SEL$2BFA4EE4 / T1@SEL$1 Predicate Information (identified by operation id): --------------------------------------------------- 1 - access("T1"."ID"="T2"."ID") 3 - filter("T1"."ID"=2) --//总之我个人还是趋向于喜欢(+)的语法. 6.附上测试脚本: $ cat expand_sql_text12c.sql variable m_sql_out clob declare m_sql_in clob ; begin select sql_fulltext into m_sql_in from v$sqlarea where sql_id='&&1'; -- dbms_sql2.expand_sql_text( -- 11g -- m_sql_in, -- :m_sql_out -- ); dbms_utility.expand_sql_text( -- 12c m_sql_in, :m_sql_out ); end; / set long 20000 column m_sql_out format a160 print m_sql_out $ cat 10053x.sql execute dbms_sqldiag.dump_trace(p_sql_id=>'&1',p_child_number=>&2,p_component=>'Compiler',p_file_id=>'a'||'&&1'); $ cat dpc.sql set verify off --select * from table(dbms_xplan.display_cursor(NVL('&1',NULL),NULL,'ALLSTATS LAST PEEKED_BINDS &2 cost partition')); select * from table(dbms_xplan.display_cursor(NVL('&1',NULL),NULL,'ALL ALLSTATS LAST PEEKED_BINDS cost partition -projection -outline &2')); prompt prompt argment : typical all advanced partition predicate remote note parallel projection alias peeked_binds outline adaptive prompt
[20200711]关于左右连接的问题.txt
来源:这里教程网
时间:2026-03-03 15:58:03
作者:
编辑推荐:
- oracle级联删除用户,删除表空间03-03
- [20200711]关于左右连接的问题.txt03-03
- Oracle 清理SYSAUX表空间03-03
- Oracle紧急固定执行计划之手段03-03
- 外键无索引对数据库的影响以及增加索引后的效果03-03
- 19c rac数据库如何添加mgmt03-03
- Oracle 事务流程分析03-03
- Oracle 11G DBMS_REDEFINITION修改表数据类型03-03
下一篇:
相关推荐
-
雷神推出 MIX PRO II 迷你主机:基于 Ultra 200H,玻璃上盖 + ARGB 灯效
2 月 9 日消息,雷神 (THUNDEROBOT) 现已宣布推出基于英
-
制造商 Musnap 推出彩色墨水屏电纸书 Ocean C:支持手写笔、第三方安卓应用
2 月 10 日消息,制造商 Musnap 现已在海外推出一款 Oce
热文推荐
- Oracle紧急固定执行计划之手段
Oracle紧急固定执行计划之手段
26-03-03 - 外键无索引对数据库的影响以及增加索引后的效果
外键无索引对数据库的影响以及增加索引后的效果
26-03-03 - 19c rac数据库如何添加mgmt
19c rac数据库如何添加mgmt
26-03-03 - 质量内建七步法(转载)
质量内建七步法(转载)
26-03-03 - 微信小程序怎么做
微信小程序怎么做
26-03-03 - Oracle RMAN备份实战
Oracle RMAN备份实战
26-03-03 - oracle19c对数据库客户端和jdbc版本要求
oracle19c对数据库客户端和jdbc版本要求
26-03-03 - ORA-00904: "wm_concat":invalid identifier错误如何解决?
- 都有哪些好用的项目管理工具?
都有哪些好用的项目管理工具?
26-03-03 - 甲骨文宣布Oracle自治数据库现可部署至客户数据中心
甲骨文宣布Oracle自治数据库现可部署至客户数据中心
26-03-03
