【问题标题】:In DB2, can a CTE be used in the table-expression of a Merge or Update statement..?在 DB2 中,可以在 Merge 或 Update 语句的表表达式中使用 CTE 吗?
【发布时间】:2019-08-30 15:20:25
【问题描述】:

在 DB2-400 v7r3m0 中,能否在 Merge 或 Update 语句的表表达式中使用公用表表达式 (CTE)?

this article,表面上与我的问题完全相同。但是,该文章已有 8 年历史,OP、答案或 cmets 均未指示 DB2 的版本。在 DB2 的许多年、平台和版本中,可能已经发生了一些变化或改进,现在允许我做我想做的事情。

下面是一个生成三个结果表的 SQL 脚本。有临时表、表表达式和 CTE。整个事情都有效,除了带有CTE3的注释部分,它显示以下错误:

SQL Error [42601]: [SQL0199] Keyword AS not expected. Valid tokens: FULL LEFT CROSS INNER RIGHT EXCEPTION.

我也用 Update 语句尝试过这个,并收到一个类似的错误,表明需要不同的关键字。

注释的 SECTION 是其上面语句的近乎精确的副本,唯一的变化是 CTE。可以使评论的部分起作用..吗?

-- CREATE HYPOTHETICAL TABLE. USE A CTE.
DECLARE GLOBAL TEMPORARY TABLE SESSION.TESTTABLE
    AS  (   WITH CTE1 AS (  SELECT      *
                            FROM        TABLE(VALUES(1,'BE'),(2,'BI'),(3,'BN')
                                             ) AS TMP (ID,PCLASS)
                         )
            SELECT  *
            FROM    CTE1
        )   WITH DATA WITH REPLACE ;

-- CREATE TABLE WITH CHANGES TO PUT IN PREVIOUS TABLE.
DECLARE GLOBAL TEMPORARY TABLE SESSION.NEWVALUES
    AS  (   SELECT      *
            FROM        TABLE(VALUES(1,'XX'),(2,'YY'),(3,'ZZ')
                        ) AS TMP (ID,QCLASS)
        )   WITH DATA WITH REPLACE ;

-- SHOW THE FIRST TABLE.
SELECT      *
FROM        SESSION.TESTTABLE ;

-- MAKE A SIMPLE WORKING CTE, AND USE IT TO SHOW THE 2ND TABLE.
WITH        CTE2 AS (   SELECT  ID, QCLASS 
                        FROM    SESSION.NEWVALUES
                    )
SELECT      * 
FROM        CTE2 ;

-- THE FOLLOWING WORKS. IT MERGES CHANGES FROM 2ND TABLE INTO THE 1ST.
MERGE INTO      SESSION.TESTTABLE AS TT
USING           (   SELECT  ID, QCLASS 
                    FROM    SESSION.NEWVALUES
                )   AS NV   ON TT.ID = NV.ID
--WHEN MATCHED    THEN              -- UPDATE ALL RECORDS
WHEN MATCHED    AND TT.ID=2 THEN    -- UPDATE ONLY RECORD #2
                    UPDATE SET TT.PCLASS = NV.QCLASS ;

-- THIS FOLLOWING DOESN'T WORK AND DISPLAYS THIS ERROR:
--      SQL Error [42601]: [SQL0199] Keyword AS not expected. 
--      Valid tokens: FULL LEFT CROSS INNER RIGHT EXCEPTION.
/*
MERGE INTO      SESSION.TESTTABLE AS TT
USING           (   WITH CTE3 AS (   SELECT  ID, QCLASS 
                                     FROM    SESSION.NEWVALUES
                                 )
                    SELECT  * 
                    FROM    CTE3     -- CTE USED HERE
                )   AS NV   ON TT.ID = NV.ID
--WHEN MATCHED    THEN              -- UPDATE ALL RECORDS
WHEN MATCHED    AND TT.ID=2 THEN    -- UPDATE ONLY RECORD #2
                    UPDATE SET TT.PCLASS = NV.QCLASS ;
*/

-- SHOW THE FIRST TABLE AGAIN, BUT NOW WITH THE CHANGES.
SELECT      *
FROM        SESSION.TESTTABLE ;

【问题讨论】:

  • 我已经编辑了 OP 以表明链接的文章是 8 岁。从那时起,DB2 发生了许多变化和改进,现在我想做的事情可能成为可能。
  • 很公平。不幸的是,据我所知,答案仍然是一样的......我还没有机会查看 7.4 的文档或使用它,但是我在我阅读的 IBM i 文章中没有看到任何内容也可以。
  • 谢谢。尽管文章年代久远,但我很确定将 CTE 链展开为子选择的老鼠巢的想法仍然是增加卷积和降低可读性的完全有效的方法。我只是想避免它。 =-)
  • 你没有看错!仅仅因为某事是实现目标的最佳方式并不能使它成为一种好方式:)

标签: db2 db2-400


【解决方案1】:

此处记录了 Db2 for i 7.4 的 WITH 公用表表达式 (CTE)

https://www.ibm.com/support/knowledgecenter/en/ssw_ibm_i_74/db2/rbafzintsel.htm

它表明您可以在 CTE 之后使用 全选

这里记录了更新

https://www.ibm.com/support/knowledgecenter/en/ssw_ibm_i_74/db2/rbafzupdt.htm

但没有显示UPDATE 可以使用 CTE,尽管它确实说您可以更新(可更新)VIEW,并且视图支持 CTE https://www.ibm.com/support/knowledgecenter/en/ssw_ibm_i_74/db2/rbafzhcview.htm

MERGE 的情况类似

https://www.ibm.com/support/knowledgecenter/en/ssw_ibm_i_74/db2/rbafzmerge.htm

【讨论】:

  • 感谢您的链接。我确实参考了UPDATEMERGE 的那些页面(对于我的OP 中提到的7.3),仅凭我就无法辨别您指出的细节。但现在我清楚地看到了它们。我会考虑其他选项,例如嵌套子选择或可更新视图,可能是后者。
猜你喜欢
  • 1970-01-01
  • 2011-02-25
  • 1970-01-01
  • 1970-01-01
  • 2012-09-19
  • 1970-01-01
  • 2015-07-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多