没有得到ORA-25156"旧样式外连接(+)不能用于ANSI连接"我应该

Ben*_*Ben 5 sql oracle oracle12c

将一些旧式连接转换为SQL-92样式时,a (+)意外地留在查询中.当我预期错误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');
Run Code Online (Sandbox Code Playgroud)

正在转换如下(更复杂的)查询

select *
  from outer_join oj
     , inner_join ij
 where ij.id = oj.id(+);
Run Code Online (Sandbox Code Playgroud)

并且错误地将查询转换如下

select *
  from outer_join oj
  join inner_join ij
    on ij.id = oj.id(+);
Run Code Online (Sandbox Code Playgroud)

这会产生预期的结果,但是,它非常危险,因为:

  • 有人可以很容易地假设INNER JOIN而不是OUTER JOIN(猜测发生了什么......)从而在再次更改查询时导致意外错误
  • 展出的行为可能在将来发生变化,导致许多地方出现错误
  • 它似乎与文档相矛盾

    您不能在同样包含FROM子句连接语法的查询块中指定(+)运算符.

  • 使用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
Run Code Online (Sandbox Code Playgroud)

如果我添加第三个表

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');
Run Code Online (Sandbox Code Playgroud)

然后当旧式连接位于查询的"中间"时,没有错误

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
Run Code Online (Sandbox Code Playgroud)

如果连接位于查询的"结尾",则会引发正确的错误(!).

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
Run Code Online (Sandbox Code Playgroud)

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

我已经在12.1.0.1上对此进行了测试,但如果它特定于此版本,我会感到惊讶......

nim*_*dil 1

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

我猜你可以将 (+) 打包到 ON 中,但错误是针对 WHERE 子句的,这很混乱。