SQL - 在 IBM DB2 存储过程中的 for 循环内声明游标
SQL - Declare cursor inside for loop in IBM DB2 Stored Procedure
我正在尝试使用 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
当我在下面尝试这个时,它失败了。我想在我声明的变量的帮助下从某个 table 中提取结果,并且如果结果包含任何行,则只做一些事情(在这个例子中是插入):
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
我该如何解决这个问题?
不需要 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
虽然 Wen-Yi Chua 的回答有效,但这里使用 EXISTS
谓词代替聚合更有效:
IF EXIST (SELECT 1 FROM ML_ANOMALY_EVENTS
WHERE TAG_GROUP=TAG_GROUP_TEMP AND DATETIME >= DATETIME_TEMP) THEN ...
尤其是当您希望条件在大多数情况下为真时。 EXISTS
将在找到与搜索条件匹配的单个记录后立即 return,而带有 COUNT(*)
的查询将必须读取所有匹配的记录。
我正在尝试使用 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
当我在下面尝试这个时,它失败了。我想在我声明的变量的帮助下从某个 table 中提取结果,并且如果结果包含任何行,则只做一些事情(在这个例子中是插入):
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
我该如何解决这个问题?
不需要 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
虽然 Wen-Yi Chua 的回答有效,但这里使用 EXISTS
谓词代替聚合更有效:
IF EXIST (SELECT 1 FROM ML_ANOMALY_EVENTS
WHERE TAG_GROUP=TAG_GROUP_TEMP AND DATETIME >= DATETIME_TEMP) THEN ...
尤其是当您希望条件在大多数情况下为真时。 EXISTS
将在找到与搜索条件匹配的单个记录后立即 return,而带有 COUNT(*)
的查询将必须读取所有匹配的记录。