子查询中的公共表表达式

发布于 2024-11-26 06:02:05 字数 729 浏览 3 评论 0原文

我请求帮助了解 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 子句 - 这两个查询都是动态生成的列、条件、安全性等。 另外,上述查询本身可以作为子查询在另一个查询中使用。 总结一下,原理就是动态生成视图,以后可以重复使用。某些查询可能还会将多达 10-12 个这样的动态视图合并在一起。 问题是应用程序应该与数据库无关,至少就 PG、Oracle 和 SQL 而言。对于 DB2 而言,不支持的功能根本不会实现。

I would request for help in understanding which all RDBMS from Oracle, DB2, Sybase support a common table expression (CTE) in a sub-query. I am aware that PostgreSQL does while MS SQL Server does not.

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>>

I am unable to define the with clause outside the sub-queries - both the queries are dynamically generated w.r.t. the columns, criteria, security, etc.
Also, the above query itself may be used in another query as a sub-query.
In summary, the principle is dynamically generated views, re-usable later. Some queries may have upto 10-12 such dynamic views being merged together as well.
The problem is that the application is supposed to be database-agnostic at least so far as PG, Oracle & DB2 are concerned and features not supported by one are not implemented at all.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

寂寞美少年 2024-12-03 06:02:05

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

您可以在任何顶级 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;

Yes, you can use CTE's in subqueries in Oracle. From the Oracle 11g docs:

You can specify this clause in any top-level SELECT statement and in
most types of subqueries. The query name is visible to the main query
and to all subsequent subqueries. For recursive subquery factoring,
the query name is even visible to the subquery that defines the query
name itself.

As an example, this works in 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;
梦在夏天 2024-12-03 06:02:05

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

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

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

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

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

That's not directly an answer to your question, but maybe you can think about this:

SQL Server seems to limit the semantics (not necessarily the syntax) of SQL where it makes sense to do so. For instance, you cannot have a subquery with an ORDER BY clause, if you don't also specify a TOP n clause. This makes sense, as ordered subqueries are pointless unless they have limits. Other RDBMS allow for such pointlessness.

In your case (that's just a guess), having CTE's in subqueries only makes limited sense, because you can rewrite your whole query in a way that the CTE's are declared at the top-most level. The only difference you'll have is the scope and maybe the readability of each declaration.

On the other hand, CTE's allow for recursive queries, which might be very hard to apply when CTE's are declared in subqueries...

Since you need to implement database-agnostic SQL, I recommend you do not make heavy use of CTE's yet. If CTE's are simple, you can always rewrite them as simple views...

南街九尾狐 2024-12-03 06:02:05

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

The newer Microsoft SQL Server versions do support CTE's.

亢潮 2024-12-03 06:02:05

虽然 PostgreSQL 支持 CTE,但它们是一个优化障碍,阻止将谓词或连接推送到 CTE 查询中。这使得它们在许多情况下不如简单子查询有效。

While PostgreSQL supports CTE's, they are an optimisation barrier which prevents predicate or join pushing into the CTE query. This makes them less effective in many cases than a simple subquery.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文