sql - 我应该得到 ORA-25156 "old style outer join (+) cannot be used with ANSI join"

标签 sql oracle oracle12c

将一些旧式连接转换为 SQL-92 样式时 (+)被意外留在查询中。当我预期错误 ORA-25156:旧式外连接 (+) 不能与要引发的 ANSI 连接一起使用时,没有引发错误。

我有以下表格:

create table inner_join ( 
   id integer
 , some_data varchar2(32)
   );

insert into inner_join values (1, 'a');
insert into inner_join values (2, 'b');

create table outer_join ( 
   id integer
 , some_data varchar2(32)
   );

insert into outer_join values(2, 'c');
insert into outer_join values(3, 'd');

正在转换如下(更复杂的)查询
select *
  from outer_join oj
     , inner_join ij
 where ij.id = oj.id(+);

并且错误地将查询转换如下
select *
  from outer_join oj
  join inner_join ij
    on ij.id = oj.id(+);

这会产生预期的结果,但是,它非常危险,因为:
  • 有人很容易假设 INNER JOIN 而不是 OUTER JOIN 是有意的(猜猜发生了什么......)从而在再次更改查询时导致意外错误
  • 显示的行为将来可能会发生变化,从而导致许多地方出现错误
  • 好像是contradict the documentation

    You cannot specify the (+) operator in a query block that also contains FROM clause join syntax.

  • 使用 SQL-92 标准的一个显着好处是,当代码中出现错误(即缺少连接条件)时,会出现错误

  • 我总是希望在应该提出 ORA-25156 的时候提出。

    为了演示这个问题:如果我运行这些查询,我应该不会收到错误
    select *
      from outer_join oj
      join inner_join ij
        on ij.id = oj.id(+);
    
     ID SOME_DATA  ID SOME_DATA
    --- --------- --- ---------
      2 c           2 b
                    1 a
    
    
    select *
      from inner_join ij
      join outer_join oj
        on ij.id = oj.id(+);
    
     ID SOME_DATA  ID SOME_DATA
    --- --------- --- ---------
      2 b           2 c
      1 a
    

    如果我添加第三个表
    create table middle_join ( 
       id integer
     , some_data varchar2(32)
       );
    
    insert into middle_join values (1, 'e');
    insert into middle_join values (2, 'f');
    insert into middle_join values (3, 'g');
    

    那么当旧式连接位于查询的“中间”时,就没有错误
    select *
      from inner_join ij
      join outer_join oj
        on ij.id = oj.id(+)
      join middle_join mj
        on ij.id = mj.id;
    
     ID SOME_DATA  ID SOME_DATA  ID SOME_DATA
    --- --------- --- --------- --- ---------
      1 a                         1 e
      2 b           2 c           2 f
    

    如果连接位于查询的“结尾”,则会引发正确的错误(!)。
    select *
      from inner_join ij
      join middle_join mj
        on ij.id = mj.id
      join outer_join oj
        on ij.id = oj.id(+);
        on ij.id = oj.id(+)
                   *
    ERROR at line 6:
    ORA-25156: old style outer join (+) cannot be used with ANSI joins
    

    为什么会这样?如何确保在所有情况下都引发 ORA-25156 以避免容易出错和将来出现问题?

    我已经在 12.1.0.1 上测试过这个,但如果它特定于这个版本,我会感到惊讶......

    最佳答案

    我相信当您尝试在 ANSI 语法查询的 WHERE 子句中使用 (+) 时会引发错误。当您尝试在 ON 子句中执行此操作时没有错误,因为在 Oracle 旧的蹩脚语法中,ON 子句不存在。

    我想您可以将 (+) 打包到 ON 中很麻烦,但错误是针对 WHERE 子句的。

    关于sql - 我应该得到 ORA-25156 "old style outer join (+) cannot be used with ANSI join",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41979162/

    相关文章:

    Oracle 将天到秒的间隔与整数进行比较

    json - 在 oracle 12c 中以 JSON 形式返回 sql 查询的结果

    sql - 如何在 PL/SQL 中捕获约束冲突?

    mysql - 内连接嵌套在更新语句 SQL 中

    SQL 按日期复制行到今天

    sql - 错误 ORA-02270 : no matching unique or primary key for this column-list

    sql - 在 Oracle 中的每个级别计算最小值的分层查询

    sql - 如何比较当前时间以检索存储在 SQL 中的记录

    sql - mysql左连接升序

    java - ORA-00933 SQL 命令未正确结束但在 SQL Developer 中正常