【问题标题】:SQL - Declare cursor inside for loop in IBM DB2 Stored ProcedureSQL - 在 IBM DB2 存储过程中的 for 循环内声明游标
【发布时间】:2018-08-28 04:03:13
【问题描述】:

我正在尝试使用 for 循环从游标遍历存储过程中的结果。循环在以下示例中正常工作:

CREATE OR REPLACE PROCEDURE ML_ANOMALY_EVENT_CREATOR ()
    DYNAMIC RESULT SETS 1
P1: BEGIN

    DECLARE DATETIME_TEMP TIMESTAMP(6);
    DECLARE TAG_GROUP_TEMP VARCHAR(50);
    DECLARE EVENT_CODE VARCHAR(100);
    DECLARE STMT VARCHAR(1000);
    SET STMT = 'INSERT INTO ML_ANOMALY_EVENTS VALUES(?, ?, CURRENT TIMESTAMP, ?, CURRENT TIMESTAMP)';
    PREPARE S1 FROM STMT;

    FOR v AS AD_DATA CURSOR FOR (SELECT DATETIME, TAG_GROUP FROM ML_AD_MV WHERE DATETIME > (SELECT MAX(DATETIME_END) FROM ML_ANOMALY_EVENTS) AND ANOMALY=2 ORDER BY 2, 1)
        DO
            SET DATETIME_TEMP = v.DATETIME;
            SET TAG_GROUP_TEMP = v.TAG_GROUP;
            SET EVENT_CODE = 'TEST';
            EXECUTE S1 USING EVENT_CODE, TAG_GROUP_TEMP, DATETIME_TEMP;
    END FOR;

END P1

当我在下面尝试这个时,它失败了。我想借助我声明的变量从某个表中提取结果,并且只有在结果包含任何行时才执行某些操作(在本例中为插入):

CREATE OR REPLACE PROCEDURE ML_ANOMALY_EVENT_CREATOR ()
    DYNAMIC RESULT SETS 1
P1: BEGIN

    DECLARE DATETIME_TEMP TIMESTAMP(6);
    DECLARE TAG_GROUP_TEMP VARCHAR(50);
    DECLARE EVENT_CODE VARCHAR(100);
    DECLARE STMT VARCHAR(1000);
    SET STMT = 'INSERT INTO ML_ANOMALY_EVENTS VALUES(?, ?, CURRENT TIMESTAMP, ?, CURRENT TIMESTAMP)';
    PREPARE S1 FROM STMT;

    FOR v AS AD_DATA CURSOR FOR (SELECT DATETIME, TAG_GROUP FROM ML_AD_MV WHERE DATETIME > (SELECT MAX(DATETIME_END) FROM ML_ANOMALY_EVENTS) AND ANOMALY=2 ORDER BY 2, 1)
        DO
            SET DATETIME_TEMP = v.DATETIME;
            SET TAG_GROUP_TEMP = v.TAG_GROUP;
            SET EVENT_CODE = 'TEST';
            --EXECUTE S1 USING EVENT_CODE, TAG_GROUP_TEMP, DATETIME_TEMP;

            DECLARE EVENT_CHECKER CURSOR FOR
                SELECT * FROM ML_ANOMALY_EVENTS WHERE TAG_GROUP=TAG_GROUP_TEMP AND DATETIME >= DATETIME_TEMP;

            OPEN EVENT_CHECKER;
                IF (EVENT_CHECKER IS FOUND) THEN
                    EXECUTE S1 USING EVENT_CODE, TAG_GROUP_TEMP, DATETIME_TEMP;
                END IF;
            CLOSE EVENT_CHECKER;

    END FOR;

END P1

我该如何解决这个问题?

【问题讨论】:

  • 了解如何调试存储过程。了解如何在 SQL PL 中使用游标,特别是 OPEN event_checker 游标是不够的,您还必须从中提取值。按照 IBM 的示例 SQL PL 存储过程了解更多信息。除非您指定什么是失败(错误代码、确切结果等),否则切勿写“失败”。有更好的方法可以满足您的需求。

标签: sql stored-procedures db2 db2-luw


【解决方案1】:

虽然 Wen-Yi Chua 的回答有效,但在这里使用 EXISTS 谓词代替聚合更有效:

IF EXIST (SELECT 1 FROM ML_ANOMALY_EVENTS 
          WHERE TAG_GROUP=TAG_GROUP_TEMP AND DATETIME >= DATETIME_TEMP) THEN ...

尤其是如果您期望条件在大多数情况下为真。只要找到一条匹配搜索条件的记录,EXISTS 就会返回,而带有COUNT(*) 的查询则必须读取所有匹配的记录。

【讨论】:

    【解决方案2】:

    不需要有 event_checker 光标。试试

    if ((SELECT count(*) FROM ML_ANOMALY_EVENTS 
         WHERE TAG_GROUP=TAG_GROUP_TEMP AND DATETIME >= DATETIME_TEMP ) > 0) then
       EXECUTE S1 USING EVENT_CODE, TAG_GROUP_TEMP,DATETIME_TEMP;
    end if
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-08-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多