子查询中的公用表表达式

时间:2011-07-25 06:20:56

标签: oracle postgresql db2 sybase common-table-expression

我会请求帮助,以了解来自Oracle,DB2,Sybase的所有RDBMS在子查询中支持公共表表达式(CTE)。我知道PostgreSQL确实在MS SQL Server没有。

SELECT a.*, b.* 
 FROM (WHERE aa as (
          <<select_query>),
          SELECT * 
            FROM aa
           WHERE <<criteria>>
    ) as a
    LEFT JOIN (
        WITH bb as (
            <<select_query>
        ),
        select * from bb inner join tbl_c on <<innerjoin>> where <<criteria>>
    ) as b
    on <<join_expr>>

我无法在子查询之外定义with子句 - 这两个查询都是由w.r.t动态生成的。列,标准,安全性等 此外,上述查询本身可以在另一个查询中用作子查询。 总之,原理是动态生成的视图,以后可以重用。一些查询也可能将多达10-12个这样的动态视图合并在一起。 问题是应用程序应该与数据库无关,至少就PG,Oracle和Oracle而言。 DB2是关注的,一个不支持的功能根本没有实现。

4 个答案:

答案 0 :(得分:4)

是的,您可以在Oracle的子查询中使用CTE。来自Oracle 11g docs

  

您可以在任何顶级SELECT语句中指定此子句   大多数类型的子查询。查询名称对主查询可见   以及所有后续子查询。对于递归子查询因子分解,   查询名称甚至对定义查询的子查询可见   自称。

例如,这适用于Oracle:

SELECT a.*, b.*
  FROM (WITH aa AS
         (
           SELECT LEVEL l1, mod(level, 5) m1 FROM dual CONNECT BY LEVEL < 50
         )
         SELECT * FROM aa WHERE m1 < 3) a LEFT JOIN
       (WITH bb AS 
         (
           SELECT LEVEL l2, mod(level, 5) m2 FROM dual CONNECT BY LEVEL < 50
         )
         SELECT * FROM bb WHERE m2 BETWEEN 1 AND 4) b
        ON a.l1 = b.l2;

答案 1 :(得分:3)

这不是你问题的直接答案,但也许你可以考虑一下:

SQL Server似乎限制了SQL的语义(不一定是语法),这样做才有意义。例如,如果您还没有指定ORDER BY子句,则不能使用带有TOP n子句的子查询。这是有道理的,因为有序子查询是没有意义的,除非它们有限制。其他RDBMS允许这种无意义。

在你的情况下(这只是一个猜测),在子查询中使用CTE只是有限的意义,因为你可以用CTE在最顶层声明的方式重写你的整个查询。你唯一的区别就是每个声明的范围和可读性。

另一方面,CTE允许递归查询,当在子查询中声明CTE时,这可能很难应用......

由于您需要实现与数据库无关的SQL,我建议您不要大量使用CTE。如果CTE很简单,你总是可以将它们重写为简单的视图......

答案 2 :(得分:0)

较新的Microsoft SQL Server版本支持CTE。

答案 3 :(得分:0)

虽然PostgreSQL支持CTE,但它们是一个优化障碍,可防止谓词或连接推入CTE查询。这使得它们在很多情况下不如简单的子查询有效。