Oracle兼容-语法-Oracle(+)语法
1. 语法
1. -- LEFT JOIN
2. SELECT * FROM join_table1, join_table2 WHERE join_table1.col1 join_specification join_table2.col2(+);
4. -- RIGHT JOIN
5. SELECT * FROM join_table1, join_table2 WHERE join_table1.col1(+) join_specification join_table2.col2;
2. (+)语法使用示例及说明
创建测试表并填充测试数据
1. greatsql> CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY, c1 INT);
2. greatsql> CREATE TABLE t2 (id INT NOT NULL PRIMARY KEY, c1 INT);
3. greatsql> INSERT INTO t1 VALUES (1, 1), (2, 2), (3,3), (4,4);
4. greatsql> INSERT INTO t2 VALUES (4, 4), (3, 3), (2,2), (1,1);
6. greatsql> SELECT * FROM t1;
7. +----+------+
8. | id | c1 |
9. +----+------+
10. | 1 | 1 |
11. | 2 | 2 |
12. | 3 | 3 |
13. | 4 | 4 |
14. +----+------+
15. 4 rows in set (0.00 sec)
17. greatsql> SELECT * FROM t2;
18. +----+------+
19. | id | c1 |
20. +----+------+
21. | 4 | 4 |
22. | 3 | 3 |
23. | 2 | 2 |
24. | 1 | 1 |
25. +----+------+
26. 4 rows in set (0.00 sec)
28. greatsql> SELECT * FROM t1;
29. +----+------+
30. | id | c1 |
31. +----+------+
32. | 1 | 1 |
33. | 2 | 2 |
34. | 3 | 3 |
35. | 4 | 4 |
36. +----+------+
37. 4 rows in set (0.00 sec)
-
- 支持多种用法。
2. -- `(+)` 写在被连接表一侧,表示 t1 LEFT JOIN t2
3. greatsql> EXPLAIN SELECT * FROM t1, t2 WHERE t1.c1 = t2.c1(+);
4. +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------------------+
5. | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
6. +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------------------+
7. | 1 | SIMPLE | t1 | NULL | ALL | NULL | NULL | NULL | NULL | 4 | 100.00 | NULL |
8. | 1 | SIMPLE | t2 | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 100.00 | Using where; Using join buffer (hash join) |
9. +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------------------+
10. 2 rows in set, 1 warning (0.00 sec)
12. -- 可以看到是t1 left join t2
13. greatsql> SHOW WARNINGS;
14. *************************** 1. row ***************************
15. Level: Note
16. Code: 1003
17. Message: /* select#1 */ select `greatsql`.`t1`.`id` AS `id`,`greatsql`.`t1`.`c1` AS `c1`,`greatsql`.`t2`.`id` AS `id`,`greatsql`.`t2`.`c1` AS `c1` from `greatsql`.`t1` left join `greatsql`.`t2` on((`greatsql`.`t2`.`c1` = `greatsql`.`t1`.`c1`)) where true
19. -- `(+)` 写在主动连接表一侧,表示 t1 RIGHT JOIN t2
20. greatsql> EXPLAIN SELECT * FROM t1, t2 WHERE t1.c1 (+)= t2.c1;
21. +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------------------+
22. | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
23. +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------------------+
24. | 1 | SIMPLE | t2 | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 100.00 | NULL |
25. | 1 | SIMPLE | t1 | NULL | ALL | NULL | NULL | NULL | NULL | 4 | 100.00 | Using where; Using join buffer (hash join) |
26. +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------------------+
27. 2 rows in set, 1 warning (0.00 sec)
29. -- 可以看到是t2 left join t1
30. greatsql> SHOW WARNINGS;
31. *************************** 1. row ***************************
32. Level: Note
33. Code: 1003
34. Message: /* select#1 */ select `greatsql`.`t1`.`id` AS `id`,`greatsql`.`t1`.`c1` AS `c1`,`greatsql`.`t2`.`id` AS `id`,`greatsql`.`t2`.`c1` AS `c1` from `greatsql`.`t2` left join `greatsql`.`t1` on((`greatsql`.`t1`.`c1` = `greatsql`.`t2`.`c1`)) where true
36. -- 支持多表JOIN
37. greatsql> CREATE TABLE t3 LIKE t1;
38. greatsql> INSERT INTO t3 SELECT * FROM t1;
40. -- 等同于 t3 left join t2 left join t1
41. greatsql> EXPLAIN SELECT * FROM t1, t2, t3 WHERE t1.c1(+) = t2.c1 AND t2.c1(+) = t3.c1;
42. +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------------------+
43. | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
44. +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------------------+
45. | 1 | SIMPLE | t3 | NULL | ALL | NULL | NULL | NULL | NULL | 4 | 100.00 | NULL |
46. | 1 | SIMPLE | t2 | NULL | ALL | NULL | NULL | NULL | NULL | 4 | 100.00 | Using where; Using join buffer (hash join) |
47. | 1 | SIMPLE | t1 | NULL | ALL | NULL | NULL | NULL | NULL | 4 | 100.00 | Using where; Using join buffer (hash join) |
48. +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------------------+
49. 3 rows in set, 1 warning (0.00 sec)
51. greatsql> SHOW WARNINGS\G
52. *************************** 1. row ***************************
53. Level: Note
54. Code: 1003
55. Message: /* select#1 */ select `greatsql`.`t1`.`id` AS `id`,`greatsql`.`t1`.`c1` AS `c1`,`greatsql`.`t2`.`id` AS `id`,`greatsql`.`t2`.`c1` AS `c1`,`greatsql`.`t3`.`id` AS `id`,`greatsql`.`t3`.`c1` AS `c1` from `greatsql`.`t3` left join (`greatsql`.`t2` left join `greatsql`.`t1` on((`greatsql`.`t1`.`c1` = `greatsql`.`t2`.`c1`))) on((`greatsql`.`t2`.`c1` = `greatsql`.`t3`.`c1`)) where true
57. -- 支持多表部分JOIN
58. greatsql> CREATE TABLE t4 LIKE t1;
59. greatsql> INSERT INTO t4 SELECT * FROM t1;
61. -- 等同于 (t2 left join t1) join (t3 left join t4)
62. greatsql> EXPLAIN SELECT * FROM t1, t2, t3, t4 WHERE t1.c1(+) = t2.c1 AND t3.c1 = t4.c1(+);
63. +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------------------+
64. | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
65. +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------------------+
66. | 1 | SIMPLE | t2 | NULL | ALL | NULL | NULL | NULL | NULL | 4 | 100.00 | NULL |
67. | 1 | SIMPLE | t1 | NULL | ALL | NULL | NULL | NULL | NULL | 4 | 100.00 | Using where; Using join buffer (hash join) |
68. | 1 | SIMPLE | t3 | NULL | ALL | NULL | NULL | NULL | NULL | 4 | 100.00 | Using join buffer (hash join) |
69. | 1 | SIMPLE | t4 | NULL | ALL | NULL | NULL | NULL | NULL | 4 | 100.00 | Using where; Using join buffer (hash join) |
70. +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------------------+
71. 4 rows in set, 1 warning (0.00 sec)
73. greatsql> SHOW WARNINGS\G
74. *************************** 1. row ***************************
75. Level: Note
76. Code: 1003
77. Message: /* select#1 */ select `greatsql`.`t1`.`id` AS `id`,`greatsql`.`t1`.`c1` AS `c1`,`greatsql`.`t2`.`id` AS `id`,`greatsql`.`t2`.`c1` AS `c1`,`greatsql`.`t3`.`id` AS `id`,`greatsql`.`t3`.`c1` AS `c1`,`greatsql`.`t4`.`id` AS `id`,`greatsql`.`t4`.`c1` AS `c1` from `greatsql`.`t3` left join `greatsql`.`t4` on((`greatsql`.`t4`.`c1` = `greatsql`.`t3`.`c1`)) join `greatsql`.`t2` left join `greatsql`.`t1` on((`greatsql`.`t1`.`c1` = `greatsql`.`t2`.`c1`)) where true
-
(+)只能用在单列上,不能用于表达式或者常量。
1. -- 错误示例,报告语法错误
2. greatsql> SELECT * FROM t1, t2 WHERE t1.c1 = 0(+);
3. ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '(+)' at line 1
5. greatsql> SELECT * FROM t1, t2 WHERE (t1.c1 + t2.c1)(+) = t2.id;
6. ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '(+) = t2.id' at line 1
-
(+)只能用于WHERE表达式中的列,用在其它位置的列会忽略其作用。
1. -- 下面的示例不会按照t2.c1列排序或分组
2. greatsql> SELECT * FROM t1, t2 WHERE t1.c1 = t2.c1 ORDER BY t2.c1(+);
3. +----+------+----+------+
4. | id | c1 | id | c1 |
5. +----+------+----+------+
6. | 1 | 1 | 1 | 1 |
7. | 2 | 2 | 2 | 2 |
8. | 3 | 3 | 3 | 3 |
9. | 4 | 4 | 4 | 4 |
10. +----+------+----+------+
11. 4 rows in set (0.00 sec)
13. greatsql> SELECT t2.c1 FROM t1, t2 WHERE t1.c1 = t2.c1 GROUP BY t2.c1(+);
14. +------+
15. | c1 |
16. +------+
17. | 4 |
18. | 3 |
19. | 2 |
20. | 1 |
21. +------+
22. 4 rows in set (0.00 sec)
24. greatsql> SELECT t1.c1, t2.c1 FROM t1, t2 GROUP BY t2.c1, t1.c1 HAVING t2.c1 = t1.c1(+);
25. +------+------+
26. | c1 | c1 |
27. +------+------+
28. | 4 | 4 |
29. | 3 | 3 |
30. | 2 | 2 |
31. | 1 | 1 |
32. +------+------+
33. 4 rows in set (0.00 sec)
3. 语义检查
-
- 不能与ANSI连接同时使用。
1. greatsql> SELECT * FROM t1 LEFT JOIN t2 ON t1.c1 = t2.c1 WHERE t1.c1 = t2.c1(+);
2. ERROR 7526 (HY000): OuterJoin: old style outer join (+) cannot be used with ANSI joins
-
- 不能在关联列上指定
(+)。
- 不能在关联列上指定
1. greatsql> SELECT * FROM t1 WHERE t1.id = (SELECT c1 FROM t2 WHERE t2.c1 = t1.c1(+));
2. ERROR 7526 (HY000): OuterJoin: an outer join cannot be specified on a correlation column
-
(+)列不能外部连接到子查询上。
1. greatsql> SELECT * FROM t1 WHERE t1.c1(+) = (SELECT id FROM t2);
2. ERROR 7526 (HY000): OuterJoin: a column may not be outer-joined to a subquery
-
(+)操作符只能应用于列,不能应用于任意表达式。但任意表达式可以包含一个或多个用(+)操作符标记的列。
1. -- 合法
2. greatsql> SELECT * FROM t1, t2 WHERE t1.c1(+) + t1.c1(+) < t2.c1;
4. -- 合法
5. greatsql> SELECT * FROM t1, t2 WHERE t1.c1 + t2.c1(+) < t1.c1;
7. -- 报错
8. greatsql> SELECT * FROM t1, t2 WHERE t1.c1(+) + t2.c1(+) < t2.c1;
9. ERROR 7526 (HY000): OuterJoin: a predicate may reference only one outer-joined table
-
- 包含
(+)操作符的WHERE条件不能与其它条件使用OR操作符组合。
- 包含
1. greatsql> SELECT * FROM t1, t2 WHERE t1.c1+t2.c1(+) < t1.c1 OR t1.c1 = 5;
2. ERROR 7526 (HY000): OuterJoin: outer join operator (+) not allowed in operand of OR or IN
4. greatsql> SELECT * FROM t1, t2 WHERE t1.c1(+) in (t2.c1, t2.c1);
5. ERROR 7526 (HY000): OuterJoin: outer join operator (+) not allowed in operand of OR or IN
7. -- IN被优化改写为=
8. greatsql> EXPLAIN FORMAT=JSON SELECT * FROM t1, t2 WHERE t1.c1(+) in (t2.c1);
9. ...
10. "attached_condition": "<if>(is_not_null_compl(t1), (`greatsql`.`t1`.`c1` = `greatsql`.`t2`.`c1`), true)"
11. ...
-
- 有几种不能连接的场景
1. -- 不能自己与自己
2. greatsql> SELECT * FROM t1 WHERE t1.c1(+) = t1.c1;
3. ERROR 7526 (HY000): OuterJoin: two tables cannot be outer-joined to each other
5. -- 两表左右重复连接
6. greatsql> SELECT * FROM t1, t2 WHERE t1.c1 = t2.c1(+) AND t1.c1(+) = t2.c1;
7. ERROR 7526 (HY000): OuterJoin: two tables cannot be outer-joined to each other
9. -- 先自己连接自己,再连接其他表
10. greatsql> SELECT * FROM t1, t2 WHERE t2.c1 + t2.c1(+) < t1.c1;
11. ERROR 7526 (HY000): OuterJoin: a table may be outer joined to at most one other table
13. -- 合法
14. greatsql> SELECT * FROM t1, t2 WHERE t2.c1(+) + t2.c1(+) < t1.c1;
15. +----+------+------+------+
16. | id | c1 | id | c1 |
17. +----+------+------+------+
18. | 1 | 1 | NULL | NULL |
19. | 2 | 2 | NULL | NULL |
20. | 3 | 3 | 1 | 1 |
21. | 4 | 4 | 1 | 1 |
22. +----+------+------+------+
23. 4 rows in set (0.00 sec)
-
- 一个表只能最多连接到一个表,不能连接多个表。
2. greatsql> SELECT * FROM t1, t2, t3 WHERE t1.c1(+) = t2.c1 AND t1.c1(+) = t3.c1;
3. ERROR 7526 (HY000): OuterJoin: a table may be outer joined to at most one other table
5. -- (+)所在的另外一侧,涉及多个表
6. -- Oracle 12c以上版本支持该用法
7. greatsql> SELECT * FROM t1, t2, t3 WHERE t1.c1(+) = t2.c1+t3.c1;
8. ERROR 7526 (HY000): OuterJoin: a table may be outer joined to at most one other table
-
- 投影列,
CONNECT BY,ORDER BY等不支持使用(+)运算符。
- 投影列,
1. greatsql> SELECT c1(+) FROM t1;
2. ERROR 7526 (HY000): OuterJoin: outer join operator (+) is not allowed here
- 9.以下两种情况,
(+)无意义会被可忽略 - a. 如果两表有多个连接条件,则必须为每个关联条件指定
(+),否则(+)没有意义,会被忽略,相当于INNER JOIN。 - b. 当
(+)关联的表一个在外查询,一个在内查询时,例如:SELECT * FROM t1 WHERE t1.c1 = (SELECT a FROM t2 WHERE t2.c1(+) = t1.c1);。
问题反馈
联系我们
扫码关注微信公众号

