SQL - 在IBM DB2存储过程中为for循环声明游标

时间:2018-03-19 14:40:39

标签: sql stored-procedures db2 db2-luw

我试图使用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

我该如何解决这个问题?

2 个答案:

答案 0 :(得分:1)

无需使用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

答案 1 :(得分:1)

虽然蔡文义的答案有效,但使用EXISTS谓词代替聚合更有效:

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

特别是如果您希望大多数情况下条件为真。只要找到与搜索条件匹配的单个记录,EXISTS就会返回,而COUNT(*)的查询则必须读取所有匹配的记录。