1. 问题
Kingbase如何兼容Oracle加号(+)连接操作符?
2. 文档概述
本文主要是通过调研Oracle的加号(+)操作符的功能,然后分析如何基于Kingbase实现兼容Oracle加号(+)连接操作符。
3. Oracle加号(+)操作符功能调研
Oracle中的连接类型可以分为两类:
内连接(inner join);
外连接。而外连接又分为左外连接(left join)、右外连接(right join)和全外连接(full join)。
而左右外连接除了使用left join、right join语法,外连接还可以使用加号(+)连接操作符语法。但是如果使用加号(+)连接操作符语法时,需要有一些注意事项:
(+)操作符只能出现在where子句中,并且不能与outer join语法同时使用;
当使用(+)操作符执行外连接时,如果where子句中包含有多个条件,则必须在所有条件中都包含(+)操作符;
(+)操作符只适用于列,而不能用在表达式上;
(+)操作符不能与or和in操作符一起使用;
(+)操作符只能用于实现左右外连接,而不能用于实现完全外连接。
Oracle 12c(+)操作符实例分析:
1、创建数据源
create table t1 (i int, j int) ;
insert into t1 values ( 1,2);
insert into t1 values (2,2);
insert into ti values (3,1) ;
insert into t1 values (null, null);
create table t2 as select * from t1;
========与where条件混合使用==========
2、简单等值连接条件
SQL> select * from t1, t2 where t1.i = t2.i(+);
I J I J
--------- -------- ------- --------
1 2 1 2
2 2 2 2
3 1 3 1
已选择4行。
3、如果有单表条件但是没有join条件,则(+)被忽略
SQL> select * from t1, t2 where t2.i(+)= 2;
I J I J
---------- -------- ------- --------
1 2 2 2
2 2 2 2
3 1 2 2
2 2
已选择4行。
SQL>select * from t1, t2 where t2.i = 2;
I J I J
---------- -------- ------- --------
1 2 2 2
2 2 2 2
3 1 2 2
2 2
己选择4行。
4、增加left join的右表单表条件
SQL> select * from t1,t2 where t1.i = t2.i(+) and t2.j(+) = 2;
I J I J
---------- -------- ------- --------
1 2 1 2
2 2 2 2
3 1
已选择4行。
5、如果left join 的右表单表条件不带(+),则作为普通where条件
SQL> select * from t1,t2 where t1.i = t2.i(+) and t2.j = 2;
I J I J
---------- -------- ------- --------
1 2 1 2
2 2 2 2
已选择2行。
6、如果增加left join的左表单表条件且带(+),没有意义,被忽略
SQL> select * from t1,t2 where t1.i = t2.i(+) and t1.j(+) = 2;
I J I J
---------- -------- ------- --------
1 2 1 2
2 2 2 2
已选择2行。
SQL> select * from t1,t2 where t1.i = t2.i(+) and t1.j = 2;
I J I J
---------- -------- ------- --------
1 2 1 2
2 2 2 2
已选择2行。
7、支持运算表达式
SQL> select * from t1, t2 where t1.i = t2.i(+) + 1;
I J I J
--------- -------- ------- --------
2 2 1 2
3 1 2 2
1 2
已选择4行。
8、支持like
SQL> select * from t1, t2 where t1.i like t2.j(+);
I J I J
---------- -------- ------- --------
1 2 3 1
2 2 1 2
2 2 2 2
3 1
己选择5行。
9、支持between and
SQL> select * from t1, t2 where t1.i between t2.i(+) and t2.j(+);
I J I J
---------- -------- ------- --------
3 1
2 2 2 2
2 2 1 2
1 2 1 2
已选择5行。
10、支持is
SQL> select * from t1, t2 where t1.i = t2.i(+) and t2.j(+) is not null;
I J I J
---------- -------- ------- --------
1 2 1 2
2 2 2 2
3 1 3 1
已选择4行。
11、不支持or
SQL> select * from t1, t2 where t1.i = t2.i(+) or t1.j = t2.j(+);
select * from t1, t2 where t1.i = t2.i(+) or t1.j = t2.j(+)
第1行出现错误:
ORA-01719: OR或IN操作数中不允许外部联接运算符(+)
12、 不支持not (A and B)
SQL> select * from t1,t2 where not (t1.i = t2.i(+) and t1.j = t2.j(+));
select * from t1,t2 where not (t1.i = t2.i(+) and t1.j = t2.j(+))
第1行出现错误:
ORA-01719: OR或IN操作数中不允许外部联接运算符(+)
13、 支持not A
SQL> select * from t1, t2 where not t1.i = t2.i(+);
I J I J
---------- -------- ------- --------
1 2 2 2
1 2 3 1
2 2 1 2
2 2 3 1
3 1 1 2
3 1 2 2
已选择7行。
14、 不支持IN多个值
SQL> select * from t1, t2 where t1.i in (t2.i(+), 3);
select * from t1, t2 where t1.i in (t2.i(+), 3)
第1行出现错误:
0RA-01719: OR或IN操作数中不允许外部联接运算符(+)
15、 支持IN一个值
SQL> select * from t1, t2 where t1.i in (t2.i(+));
I J I J
---------- -------- ------- --------
1 2 1 2
2 2 2 2
3 1 3 1
已选择4行。
16、 不支持子查询
SQL> select * from t1,t2 where t2.i(+) = (select max(t1.i) from t1) ;
select * from t1, t2 where t2.i(+) = (select max(t1.i) from t1)
第1行出现错误:
0RA-01799:列不能外部联接到子查询
========与ON条件混合使用==========
17、 简单等值连接条件
SQL> select * from t1 left join t2 on t1.i = t2.i(+);
I J I J
---------- -------- ------- --------
1 2 1 2
2 2 2 2
3 1 3 1
已选择4行。
18、连接类型冲突报错
SQL> select * from t1 right join t2 on t1.i = t2.i(+);
select * from t1 right join t2 on t1.i = t2.i(+)
第1行出现错误:
ORA-01468: 一个谓词只能引用一个外部联接的表
19、 left join的右表单表条件加不加(+)都是on条件
SQL> select * from t1 left join t2 on t1.i = t2.i(+) and t2.j = 2;
I J I J
---------- -------- ------- --------
1 2 1 2
2 2 2 2
3 1
已选择4行。
SQL> select * from t1 left join t2 on t1.i = t2.i(+) and t2.j(+) = 2;
I J I J
---------- -------- ------- --------
1 2 1 2
2 2 2 2
3 1
已选择4行。
20、 left join的左表单表条件加(+)会冲突
SQL> select * from t1 left join t2 on t1.i = t2.i(+) and t1.j(+) = 2;
select * from t1 left join t2 on t1.i = t2.i(+) and t1.j(+) = 2
第1行出现错误:
ORA-01468: 一个谓词只能引用一个外部联接的表
21、 full join遇到连接操作符退化成1eft join的情况
SQL> select * from t1 full join t2 on t1.j = t2.i(+);
I J I J
---------- -------- ------- --------
3 1 1 2
1 2 2 2
2 2 2 2
已选择4行。
22、 full join退化成left join,增加右表单表条件
SQL> select * from t1 full join t2 on t1.j = t2.i(+) and t2.j(+) = 2;
I J I J
---------- -------- ------- --------
3 1 1 2
1 2 2 2
2 2 2 2
已选择4行。
23、 full join退化成left join, 不带(+)的右表单表条件转变为where条件
SQL> select * from t1 full join t2 on t1.j = t2.i(+) and t2.j = 2;
I J I J
---------- -------- ------- --------
3 1 1 2
1 2 2 2
2 2 2 2
己选择3行。
24、 full join退化成left join, 增加左表单表条件, (+)被忽略
SQL> select * from t1 fu1ll join t2 on t1.j = t2.i(+) and t1.j(+) = 2;
I J I J
---------- -------- ------- --------
1 2 2 2
2 2 2 2
3 1
已选择4行。
SQL> select * from t1 full join t2 on t1.j = t2.i(+) and t1.j = 2;
I J I J
---------- -------- ------- --------
1 2 2 2
2 2 2 2
3 1
已选择4行。
4.Kingbase与Oracle加号(+)特性对比
特性对比表


5. Parsetree的结构对比分析
5.1. 不带join on的
详见https://bbs.kingbase.com.cn/thread-14537-1-1.html?_dsign=30e0d4f9
5.2. 带join on的
详见https://bbs.kingbase.com.cn/thread-14537-1-1.html?_dsign=30e0d4f9
oraclev8eftparsetree




