Oracle兼容-语法-Oracle(+)语法


1. 语法

  1. -- LEFT JOIN
  2. SELECT * FROM join_table1, join_table2 WHERE join_table1.col1 join_specification join_table2.col2(+);
  3. -- RIGHT JOIN
  4. 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);
  5. greatsql> SELECT * FROM t1;
  6. +----+------+
  7. | id | c1 |
  8. +----+------+
  9. | 1 | 1 |
  10. | 2 | 2 |
  11. | 3 | 3 |
  12. | 4 | 4 |
  13. +----+------+
  14. 4 rows in set (0.00 sec)
  15. greatsql> SELECT * FROM t2;
  16. +----+------+
  17. | id | c1 |
  18. +----+------+
  19. | 4 | 4 |
  20. | 3 | 3 |
  21. | 2 | 2 |
  22. | 1 | 1 |
  23. +----+------+
  24. 4 rows in set (0.00 sec)
  25. greatsql> SELECT * FROM t1;
  26. +----+------+
  27. | id | c1 |
  28. +----+------+
  29. | 1 | 1 |
  30. | 2 | 2 |
  31. | 3 | 3 |
  32. | 4 | 4 |
  33. +----+------+
  34. 4 rows in set (0.00 sec)
    1. 支持多种用法。
  1. -- `(+)` 写在被连接表一侧,表示 t1 LEFT JOIN t2
  2. greatsql> EXPLAIN SELECT * FROM t1, t2 WHERE t1.c1 = t2.c1(+);
  3. +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------------------+
  4. | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
  5. +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------------------+
  6. | 1 | SIMPLE | t1 | NULL | ALL | NULL | NULL | NULL | NULL | 4 | 100.00 | NULL |
  7. | 1 | SIMPLE | t2 | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 100.00 | Using where; Using join buffer (hash join) |
  8. +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------------------+
  9. 2 rows in set, 1 warning (0.00 sec)
  10. -- 可以看到是t1 left join t2
  11. greatsql> SHOW WARNINGS;
  12. *************************** 1. row ***************************
  13. Level: Note
  14. Code: 1003
  15. 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
  16. -- `(+)` 写在主动连接表一侧,表示 t1 RIGHT JOIN t2
  17. greatsql> EXPLAIN SELECT * FROM t1, t2 WHERE t1.c1 (+)= t2.c1;
  18. +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------------------+
  19. | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
  20. +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------------------+
  21. | 1 | SIMPLE | t2 | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 100.00 | NULL |
  22. | 1 | SIMPLE | t1 | NULL | ALL | NULL | NULL | NULL | NULL | 4 | 100.00 | Using where; Using join buffer (hash join) |
  23. +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------------------+
  24. 2 rows in set, 1 warning (0.00 sec)
  25. -- 可以看到是t2 left join t1
  26. greatsql> SHOW WARNINGS;
  27. *************************** 1. row ***************************
  28. Level: Note
  29. Code: 1003
  30. 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
  31. -- 支持多表JOIN
  32. greatsql> CREATE TABLE t3 LIKE t1;
  33. greatsql> INSERT INTO t3 SELECT * FROM t1;
  34. -- 等同于 t3 left join t2 left join t1
  35. greatsql> EXPLAIN SELECT * FROM t1, t2, t3 WHERE t1.c1(+) = t2.c1 AND t2.c1(+) = t3.c1;
  36. +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------------------+
  37. | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
  38. +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------------------+
  39. | 1 | SIMPLE | t3 | NULL | ALL | NULL | NULL | NULL | NULL | 4 | 100.00 | NULL |
  40. | 1 | SIMPLE | t2 | NULL | ALL | NULL | NULL | NULL | NULL | 4 | 100.00 | Using where; Using join buffer (hash join) |
  41. | 1 | SIMPLE | t1 | NULL | ALL | NULL | NULL | NULL | NULL | 4 | 100.00 | Using where; Using join buffer (hash join) |
  42. +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------------------+
  43. 3 rows in set, 1 warning (0.00 sec)
  44. greatsql> SHOW WARNINGS\G
  45. *************************** 1. row ***************************
  46. Level: Note
  47. Code: 1003
  48. 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
  49. -- 支持多表部分JOIN
  50. greatsql> CREATE TABLE t4 LIKE t1;
  51. greatsql> INSERT INTO t4 SELECT * FROM t1;
  52. -- 等同于 (t2 left join t1) join (t3 left join t4)
  53. greatsql> EXPLAIN SELECT * FROM t1, t2, t3, t4 WHERE t1.c1(+) = t2.c1 AND t3.c1 = t4.c1(+);
  54. +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------------------+
  55. | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
  56. +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------------------+
  57. | 1 | SIMPLE | t2 | NULL | ALL | NULL | NULL | NULL | NULL | 4 | 100.00 | NULL |
  58. | 1 | SIMPLE | t1 | NULL | ALL | NULL | NULL | NULL | NULL | 4 | 100.00 | Using where; Using join buffer (hash join) |
  59. | 1 | SIMPLE | t3 | NULL | ALL | NULL | NULL | NULL | NULL | 4 | 100.00 | Using join buffer (hash join) |
  60. | 1 | SIMPLE | t4 | NULL | ALL | NULL | NULL | NULL | NULL | 4 | 100.00 | Using where; Using join buffer (hash join) |
  61. +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------------------+
  62. 4 rows in set, 1 warning (0.00 sec)
  63. greatsql> SHOW WARNINGS\G
  64. *************************** 1. row ***************************
  65. Level: Note
  66. Code: 1003
  67. 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. (+) 只能用在单列上,不能用于表达式或者常量。
  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
  4. greatsql> SELECT * FROM t1, t2 WHERE (t1.c1 + t2.c1)(+) = t2.id;
  5. 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
    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)
  12. greatsql> SELECT t2.c1 FROM t1, t2 WHERE t1.c1 = t2.c1 GROUP BY t2.c1(+);
  13. +------+
  14. | c1 |
  15. +------+
  16. | 4 |
  17. | 3 |
  18. | 2 |
  19. | 1 |
  20. +------+
  21. 4 rows in set (0.00 sec)
  22. greatsql> SELECT t1.c1, t2.c1 FROM t1, t2 GROUP BY t2.c1, t1.c1 HAVING t2.c1 = t1.c1(+);
  23. +------+------+
  24. | c1 | c1 |
  25. +------+------+
  26. | 4 | 4 |
  27. | 3 | 3 |
  28. | 2 | 2 |
  29. | 1 | 1 |
  30. +------+------+
  31. 4 rows in set (0.00 sec)

3. 语义检查

    1. 不能与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. 不能在关联列上指定 (+)
  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. (+) 列不能外部连接到子查询上。
  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. (+) 操作符只能应用于列,不能应用于任意表达式。但任意表达式可以包含一个或多个用 (+) 操作符标记的列。
  1. -- 合法
  2. greatsql> SELECT * FROM t1, t2 WHERE t1.c1(+) + t1.c1(+) < t2.c1;
  3. -- 合法
  4. greatsql> SELECT * FROM t1, t2 WHERE t1.c1 + t2.c1(+) < t1.c1;
  5. -- 报错
  6. greatsql> SELECT * FROM t1, t2 WHERE t1.c1(+) + t2.c1(+) < t2.c1;
  7. ERROR 7526 (HY000): OuterJoin: a predicate may reference only one outer-joined table
    1. 包含 (+) 操作符的 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
  3. greatsql> SELECT * FROM t1, t2 WHERE t1.c1(+) in (t2.c1, t2.c1);
  4. ERROR 7526 (HY000): OuterJoin: outer join operator (+) not allowed in operand of OR or IN
  5. -- IN被优化改写为=
  6. greatsql> EXPLAIN FORMAT=JSON SELECT * FROM t1, t2 WHERE t1.c1(+) in (t2.c1);
  7. ...
  8. "attached_condition": "<if>(is_not_null_compl(t1), (`greatsql`.`t1`.`c1` = `greatsql`.`t2`.`c1`), true)"
  9. ...
    1. 有几种不能连接的场景
  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
  4. -- 两表左右重复连接
  5. greatsql> SELECT * FROM t1, t2 WHERE t1.c1 = t2.c1(+) AND t1.c1(+) = t2.c1;
  6. ERROR 7526 (HY000): OuterJoin: two tables cannot be outer-joined to each other
  7. -- 先自己连接自己,再连接其他表
  8. greatsql> SELECT * FROM t1, t2 WHERE t2.c1 + t2.c1(+) < t1.c1;
  9. ERROR 7526 (HY000): OuterJoin: a table may be outer joined to at most one other table
  10. -- 合法
  11. greatsql> SELECT * FROM t1, t2 WHERE t2.c1(+) + t2.c1(+) < t1.c1;
  12. +----+------+------+------+
  13. | id | c1 | id | c1 |
  14. +----+------+------+------+
  15. | 1 | 1 | NULL | NULL |
  16. | 2 | 2 | NULL | NULL |
  17. | 3 | 3 | 1 | 1 |
  18. | 4 | 4 | 1 | 1 |
  19. +----+------+------+------+
  20. 4 rows in set (0.00 sec)
    1. 一个表只能最多连接到一个表,不能连接多个表。
  1. greatsql> SELECT * FROM t1, t2, t3 WHERE t1.c1(+) = t2.c1 AND t1.c1(+) = t3.c1;
  2. ERROR 7526 (HY000): OuterJoin: a table may be outer joined to at most one other table
  3. -- (+)所在的另外一侧,涉及多个表
  4. -- Oracle 12c以上版本支持该用法
  5. greatsql> SELECT * FROM t1, t2, t3 WHERE t1.c1(+) = t2.c1+t3.c1;
  6. ERROR 7526 (HY000): OuterJoin: a table may be outer joined to at most one other table
    1. 投影列, 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);

问题反馈

联系我们

扫码关注微信公众号

greatsql-wx