【问题标题】:Cursor with CASE带 CASE 的光标
【发布时间】:2023-03-06 18:58:01
【问题描述】:

我有一个类似这样的程序调用的 SQL 游标

   EXEC SQL

        DECLARE STOCK_070 CURSOR FOR
        SELECT
        A.CLIENT_ID,
        C1.CUR_ASMT_SCD,

        FROM VSTOCK A

        LEFT JOIN VASSES C1
        ON  C1.CLIENT_ID = A.CLIENT_ID
                  WHERE
        B1.STKPL_RULE_NBR  = :STRSN-STKPL-RULE-NBR
        AND DATE(A.CDTTM) >= :IOB3-DATE1
        AND    DATE(A.CDTTM) <= :IOB3-DATE2

  *RESTART
        AND
        (A.CLIENT_ID  = :STOCK-CLIENT-ID
         OR
         A.CLIENT_ID  > :STOCK-CLIENT-ID)
  *RESTART

        ORDER BY
             CASE WHEN C1.CUR_ASMT_SCD = '06'
                   THEN 1
             WHEN  C1.CUR_ASMT_SCD = '04'
                   THEN 2
             WHEN  C1.CUR_ASMT_SCD = '07'
                   THEN 3
                 ,A.CLIENT_ID
                  END
         END-EXEC.
        EXEC SQL

这在没有 CASE 语句的情况下有效。 但是,当然,在添加 CASE 之后,行为会变得混乱,因为 RESTART 不考虑 CASE。

进一步解释 - 它是一个游标,所以它被称为 3 次 MaxCall(MaxCall 在程序中定义,此处未显示)。然后光标关闭。然后,如果用户需要更多结果,则光标会重新启动。因此,为什么重启代码很重要——它告诉数据库不要从头开始。

例如,

此数据集 -(格式为 A.CLIENT_ID-C1.CUR_ASMT_SCD)= (20-6,21-6,22-6,23-6,01-4,27-04,29-4)。

应按此顺序显示:

 20,21,22,23,01,27,29

如果 MaxCall 为 3,并且 SQL 中没有 RESTART CODE - 它会返回

 20,21,22,20,21,22,20,21,22 ... ad infinitum.
 (which explains why a Restart is needed).

使用当前显示的 Restart(在添加 Order by 中的 CASE 语句之后):

 20,21,22,23,27,29

遗漏一些结果(因为 Client 01 低于 23,因此被丢弃)。

所以,我需要一种方法来更改重启代码,以说明 Order By 条款中添加的 CASE 语句。

有没有办法通过 SQL 解决这个问题?

【问题讨论】:

  • 为什么在用数字计算时使用前导零?整数没有前导零。你为什么认为这一行被丢弃 - 这对我来说没有意义......
  • 你为什么用(A.CLIENT = :STOCK-CLIENT) OR (A.CLIENT &gt; :STOCK-CLIENT)而不是(A.CLIENT &gt;= :STOCK-CLIENT)
  • 另外,您使用的是什么版本的 DB2,在什么平台上?最后,请在RESTART 周围添加代码,因为这显然是问题所在。 /* lots of statements */ 是什么,可以举个例子。
  • 稍微更新了一下——看看有没有帮助?
  • 真的在Cics下运行吗???,为什么要在CICS下重启

标签: sql db2 cics


【解决方案1】:

在我看来,您在 CASE 语句中缺少 END,也许在光标上使用 WITH HOLD 会有所帮助。

EXEC SQL

    DECLARE STOCK_070 CURSOR WITH HOLD FOR
    SELECT
    A.CLIENT_ID,
    C1.CUR_ASMT_SCD,

    FROM VSTOCK A

    LEFT JOIN VASSES C1
    ON  C1.CLIENT_ID = A.CLIENT_ID
              WHERE
    B1.STKPL_RULE_NBR  = :STRSN-STKPL-RULE-NBR
    AND DATE(A.CDTTM) >= :IOB3-DATE1
    AND    DATE(A.CDTTM) <= :IOB3-DATE2

*RESTART
    AND
    (A.CLIENT_ID  = :STOCK-CLIENT-ID
     OR
     A.CLIENT_ID  > :STOCK-CLIENT-ID)
*RESTART

    ORDER BY
         CASE WHEN C1.CUR_ASMT_SCD = '06'
               THEN 1
         WHEN  C1.CUR_ASMT_SCD = '04'
               THEN 2
         WHEN  C1.CUR_ASMT_SCD = '07'
               THEN 3
         END
             ,A.CLIENT_ID

     END-EXEC.
    EXEC SQL

【讨论】:

  • 即便如此,这也不是问题的核心。
  • 我不确定如果没有结束代码将如何正常工作。纠正后行为是否仍然存在?
  • 是的...这是一个错字...刚刚编辑过。原来的代码有END...粘贴错了。
  • 很公平,在使用 WITH HOLD 的 DECLARE CURSOR 行中查看我修改后的代码。我不确定您使用的是哪个版本的 DB2,但ibm.com/support/knowledgecenter/en/SSEPEK_11.0.0/apsg/src/tpc/… 上的 IBM 文档似乎是一个好的开始。
  • 我通读了 With Hold,但我不确定它是否适用。这是针对在 CICS 中运行的程序 - 因此在每个 MaxCall 循环之后应用关闭光标......并且从我阅读和测试的内容来看 - 在关闭光标上删除了保持。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-10
  • 2019-01-25
  • 1970-01-01
相关资源
最近更新 更多