【问题标题】:Are nested parentheses in the FROM clause valid Oracle SQL syntax?FROM 子句中的嵌套括号是有效的 Oracle SQL 语法吗?
【发布时间】:2016-04-17 17:37:23
【问题描述】:

此查询是否使用正确的 Oracle 语法?

select * from ( ( ( dual a) ) ) where a.dummy = 'X';

它适用于 11g 和 12c,但它是真正有效的语法吗?还是这只是一个编译器“错误”,将来可能会修复,导致代码失败?

我怀疑这是正确的语法,原因如下:

  1. 除了添加额外的括号外,它似乎没有做任何事情。像 ((1+2)*3) 这样的表达式显然可以从嵌套括号中受益,但我看不出它们对 FROM 子句有何帮助。当我查看上面的查询时,别名“a”看起来超出了范围。
  2. 我在SQL Language Reference syntax diagrams 中找不到此语法的有效路径。另一方面,很容易看出expressionsconditionsconditions 是如何允许嵌套括号的。 和subqueries。表达式、条件和子查询是递归的并且可以包含括号,但连接子句不是递归的。

我担心这一点,因为在类似的情况下,无效语法在一个版本中有效,然后在下一个版本中失败。例如:select (select count(*) from (select * from scott.emp where ename = dual.dummy)) from dual;。该查询在 10.2.0.1.0 中有效,但在更高版本中停止工作,因为 table references are scoped to only one level deep

原始查询的样式很糟糕,但除非确实存在问题,否则不值得更改我们的生产查询。

查询无效吗?或者该语法是否有一些正当理由,或者我缺少语法图中的某些路径?

【问题讨论】:

    标签: oracle oracle11g oracle12c


    【解决方案1】:

    除了join_clause之外,子查询可能是nested

    所以这是完美的有效语法

     (((select * from dual)));
    

    这提供了疑问查询的语法有效性的线索。

     select * from (((dual)));
    

    select 开始,我们进入 query_block

    select --> subquery --> query_block

    query_block 扩展为

    SELECT * FROM table_reference
    

    table_reference 降级到(嵌套的)subquery,可以进一步嵌套。

    table_reference --> query_table_expression --> ( subquery )

    所以继续扩展subquery 以获得所需的嵌套并最终选择TABLE 作为query_table_expression 的扩展

    但正如 MT0 和其他人指出的那样,不幸的是,这不会导致 e3 预期的结果。最大的合法查询是

    select * from (((select * from dual)));
    

    【讨论】:

    • 你可以从table_reference -> query_table_expression -> ( subquery )得到,但你不能继续做subquery -> query_table_expression -> table。所以SELECT * FROM ( SELECT * FROM table_name ) 是有效的,但SELECT * FROM ( table_name ) 不是(这就是问题所问的)。
    • @MT0 query_table_expression 扩展为 table
    • 但是subquery 不会扩展为query_table_expression,而是会扩展为query_block,即整个SELECT ... FROM ... 语句。所以,正如我之前所说,SELECT * FROM ( SELECT * FROM table_name ) 有效,但SELECT * FROM ( table_name ) 无效。
    • @MT0 就是这样!感谢您指出我的错误!我更新了答案。
    【解决方案2】:

    根据我对syntax diagram for a SELECT statement 的阅读,不允许在 SELECT 语句中的表引用周围加上括号。至于甲骨文是否会以某种方式“修复”事情,使之无效,我无法知道,但我认为这不太可能。 YMMV。

    祝你好运。

    编辑

    只是为了好玩,我想我会放下对语法图的阅读:

    正如其他人所指出的,括号允许在join_clause 周围,但dual a 不是join_clause。相反,它是query_table_expression,它是table_reference 的一部分。 dual a 不能是 join_clause - 如果是这样,它必须后跟 inner_join_clause(例如 INNER JOIN)或 outer_join_clause(例如 LEFT OUTER JOINRIGHT OUTER JOINFULL OUTER JOIN),事实并非如此。根据语法图括号,query_table_expression 周围不允许使用括号除非query_table_expression 前面有ONLY,并且在OP 的查询中dual a 前面没有ONLY。因此,我得出结论,根据 Oracle 语法图 ( ( (dual a) ) ) 在语法上是不正确的;但是,数据库似乎不同意。 :-)

    【讨论】:

      【解决方案3】:

      FROMjoin 子句 中使用括号是合法的语法,并且括号do 有效。

      考虑这个查询:

      WITH table_a AS ( SELECT rownum id FROM DUAL CONNECT BY LEVEL <= 30),
           table_b as ( SELECT rownum id FROM DUAL CONNECT BY LEVEL <= 20),
           table_c AS ( SELECT rownum id FROM DUAL CONNECT BY LEVEL <= 10)
      SELECT a.id, b.id, c.id
      FROM   table_a a left join ( table_b b inner join table_c c ON c.id = b.id ) ON b.id = a.id 
      ORDER BY 1,2,3;
      

      括号允许您对表bc 进行内部联接,然后将其外部联接到a

      没有括号,试图将其表达为左连接是不可能的。您要么不会从表 a 中获得第 11-30 行,要么表 c 的第 11-20 行将是 nulls(取决于您如何尝试这样做)。

      注意上面的查询等价于:

      WITH table_a AS ( SELECT rownum id FROM DUAL CONNECT BY LEVEL <= 30),
           table_b as ( SELECT rownum id FROM DUAL CONNECT BY LEVEL <= 20),
           table_c AS ( SELECT rownum id FROM DUAL CONNECT BY LEVEL <= 10)
      SELECT a.id, b.id, c.id
      FROM   table_b b inner join table_c c on c.id = b.id right join table_a a on a.id = b.id 
      ORDER BY 1,2,3;
      

      ,不需要括号。所以如果你真的想避免在FROM 子句中使用括号,你通常可以这样做。就个人而言,我更喜欢带括号的LEFT JOIN 方法而不是RIGHT JOIN

      【讨论】:

      • 该查询是有意义的,并解释了为什么括号可以提供帮助。我仍然想在文档图表或 BNF 描述中找到暗示这是有效语法的内容。通常,语法图很有帮助且准确。
      • 括号在连接子句周围有效,但SELECT syntax diagram 并不表示它们在表引用周围有效(这是问题中所问的)。
      • 只是出于好奇,您可以编写完全相同的 SQL,而无需括号,这仍然有效。 WITH table_a AS ( SELECT rownum id FROM DUAL CONNECT BY LEVEL &lt;= 30), table_b as ( SELECT rownum id FROM DUAL CONNECT BY LEVEL &lt;= 20), table_c AS ( SELECT rownum id FROM DUAL CONNECT BY LEVEL &lt;= 10) SELECT a.id, b.id, c.id FROM table_a a left join table_b b inner join table_c c ON c.id = b.id ON b.id = a.id ORDER BY 1,2,3;
      猜你喜欢
      • 1970-01-01
      • 2018-04-03
      • 1970-01-01
      • 2015-06-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-16
      • 2011-12-17
      相关资源
      最近更新 更多