当前位置: 首页 > 知识库问答 >
问题:

MySQL游标循环仅运行一次

时衡虑
2023-03-14

我正在使用mysql存储过程,我花了两个小时试图弄清楚为什么这个游标只运行一次。(我假设它只运行了一次,因为我运行这个存储过程后只看到一条记录——最后有一个select*from resultado命令,我从前面创建的临时表中选择了所有内容)

注意,我已经尝试过在游标中单独运行查询,它运行正常(返回了多条记录,这是应该的)。

我认为这一定与我从循环中插入数据有关(我希望在每个循环过程中向临时表中插入一行数据)。

-- cursors
DECLARE done INT DEFAULT FALSE;

-- this query, qhen run on its own, returns more than one record
DECLARE assessments_cur CURSOR FOR 
    SELECT a.id assessment_id, 
        a.name assessment_name, 
        a.create_date data_entrada,
        a.open_date data_inicio,
        a.close_date data_fim

    FROM assessments a

    WHERE a.create_date > '2013-02-28 00:00:00'
    AND a.create_date < '2014-02-28 00:00:00'
    AND a.client_id = 13
    AND a.open_date IS NOT NULL
    AND a.close_date IS NOT NULL
;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

-- tabelas temporárias
DROP TEMPORARY TABLE IF EXISTS resultado;

CREATE TEMPORARY TABLE resultado (
    nome_assessment VARCHAR(511) NOT NULL,
    segmento VARCHAR(511) NOT NULL,
    sequencia_assessment VARCHAR(511) NOT NULL,
    demanda VARCHAR(511) NULL,
    data_entrada DATETIME NOT NULL,
    data_inicio DATETIME NOT NULL,
    data_fim DATETIME NOT NULL,
    quantidade_vulnerabilidades int(11) NOT NULL,

);

OPEN assessments_cur;

REPEAT

    FETCH assessments_cur INTO 
        assessment_id_n,
        assessment_name_vr,
        data_entrada_dt,
        data_inicio_dt,
        data_fim_dt;

    SET demanda_vr = get_demanda(assessment_id_n);
    SET segmento_vr = get_segmento(assessment_id_n);

    SET quantidade_vulnerabilidades_n = get_quantidade_vulnerabilidades(assessment_id_n);

    INSERT INTO resultado(
            nome_assessment,
            segmento,
            sequencia_assessment,
            demanda,
            data_entrada,
            data_inicio,
            data_fim,
            quantidade_vulnerabilidades
        ) VALUES(
            assessment_name_vr,
            segmento_vr,
            'Foo',
            demanda_vr,
            data_entrada_dt,
            data_inicio_dt,
            data_fim_dt,
            quantidade_vulnerabilidades_n
    );


UNTIL done END REPEAT;

CLOSE assessments_cur; 

select * from resultado;

DROP TEMPORARY TABLE resultado;

共有2个答案

郭意
2023-03-14

尝试从选择查询中删除别名,如下所示:

SELECT a.id, 
    a.name, 
    a.create_date,
    a.open_date,
    a.close_date

FROM assessments a

WHERE a.create_date > '2013-02-28 00:00:00'
AND a.create_date < '2014-02-28 00:00:00'
AND a.client_id = 13
AND a.open_date IS NOT NULL
AND a.close_date IS NOT NULL
罗渝
2023-03-14

没有以下信息:

  • 表结构:评估
  • 功能:get_demandaget_segmentoget_quantidade_vulnerabilidades

然而,在一个小例子中,你可以看到光标是如何工作的。将存储过程示例与代码进行比较,并根据需要进行调整。

DELIMITER $$

DROP PROCEDURE IF EXISTS `sp_test`$$

CREATE PROCEDURE `sp_test`()
BEGIN
-- cursors
DECLARE `done` TINYINT(1) DEFAULT 0;
DECLARE `assessment_name_vr`, `segmento_vr`, `demanda_vr` VARCHAR(511);
DECLARE `data_entrada_dt`, `data_inicio_dt`, `data_fim_dt` DATETIME;
DECLARE `assessment_id_n`, `quantidade_vulnerabilidades_n` INT(11);

-- this query, qhen run on its own, returns more than one record
DECLARE `assessments_cur` CURSOR FOR 
    SELECT `a`.`id` `assessment_id`,
    `a`.`name` `assessment_name`,
    `a`.`create_date` `data_entrada`,
    `a`.`open_date` `data_inicio`,
    `a`.`close_date` `data_fim`
    FROM `assessments` `a`
    /*WHERE `a`.`create_date` > '2013-02-28 00:00:00'
    AND `a`.`create_date` < '2014-02-28 00:00:00'
    AND `a`.`client_id` = 13
    AND `a`.`open_date` IS NOT NULL
    AND `a`.`close_date` IS NOT NULL*/;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET `done` := 1;

-- tabelas temporárias
DROP TEMPORARY TABLE IF EXISTS `resultado`;

CREATE TEMPORARY TABLE `resultado` (
    `nome_assessment` VARCHAR(511) NOT NULL,
    `segmento` VARCHAR(511) NOT NULL,
    `sequencia_assessment` VARCHAR(511) NOT NULL,
    `demanda` VARCHAR(511) NULL,
    `data_entrada` DATETIME NOT NULL,
    `data_inicio` DATETIME NOT NULL,
    `data_fim` DATETIME NOT NULL,
    `quantidade_vulnerabilidades` INT(11) NOT NULL
);

OPEN `assessments_cur`;

REPEAT
    FETCH `assessments_cur` INTO 
        `assessment_id_n`,
        `assessment_name_vr`,
        `data_entrada_dt`,
        `data_inicio_dt`,
        `data_fim_dt`;

    IF (NOT `done`) THEN
        /*SET `demanda_vr` := `get_demanda`(`assessment_id_n`);*/
        SET `demanda_vr` := CONCAT('demanda_vr', CONVERT(`assessment_id_n`, CHAR));

        /*SET `segmento_vr` := `get_segmento`(`assessment_id_n`);*/
        SET `segmento_vr` := CONCAT('segmento_vr', CONVERT(`assessment_id_n`, CHAR));

        /*SET `quantidade_vulnerabilidades_n` := `get_quantidade_vulnerabilidades`(`assessment_id_n`);*/
        SET `quantidade_vulnerabilidades_n` := `assessment_id_n`;

        INSERT INTO `resultado` (
            `nome_assessment`,
            `segmento`,
            `sequencia_assessment`,
            `demanda`,
            `data_entrada`,
            `data_inicio`,
            `data_fim`,
            `quantidade_vulnerabilidades`
        )
        VALUES
        (
            `assessment_name_vr`,
            `segmento_vr`,
            'Foo',
            `demanda_vr`,
            `data_entrada_dt`,
            `data_inicio_dt`,
            `data_fim_dt`,
            `quantidade_vulnerabilidades_n`
        );
    END IF;
UNTIL `done` END REPEAT;

CLOSE `assessments_cur`;

SELECT * FROM `resultado`;

DROP TEMPORARY TABLE `resultado`;
END$$

DELIMITER ;

SQL小提琴演示

 类似资料:
  • 问题内容: 我很难弄清楚为什么while循环实际上不会循环。它运行一次并停止。 我正在尝试使其循环,以便用户能够多次转换单位。任何帮助都欢迎! 问题答案: 问题在于,当您呼叫时,它会占用该号码,但不会占用该号码之后的换行符。要解决此问题,只需在调用后放一行代码。 示例和完整说明: 假设您输入“ km”,按回车,“ 123”,按回车。从程序的角度来看,输入流为。 该代码获取值,并且使输入超出第一个。

  • 问题内容: 我正在尝试实现一个每秒循环的ScheduledExecutorService线程,但是截至目前,它仅循环一次。 我的问题是如何设置它,使其定期循环而不是一次迭代? 另外,如何将连接池传递到线程中,以便每次迭代都可以查询数据库?任何帮助深表感谢。 问题答案: http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent

  • 问题内容: 假设我在数据库(本例中为SQLServer 2008)中有一堆行,可用于创建方程式。 我需要想出一种方法来评估此表中的方程式。 公式1:12 + 12 = 24 公式2:(12-2)/ 2 = 5 我无法想到一种无需遍历行即可获得这些结果的方法。我知道如何执行此操作的唯一方法是使用游标或通过使用临时表和while循环。有没有更好的方法可以做到这一点?如果不是一般的话,什么将执行更好的游

  • 问题内容: 请解释一下如何在oracle中使用游标进行循环。 如果我使用下一个代码,一切都很好。 但是,如果我为此sql语句定义变量,它将无法正常工作。 错误:PLS-00103 问题答案: 要解决与第二种方法相关的问题,您需要使用 游标变量和打开游标并获取数据的显式方式。它不是 允许在循环中使用游标变量: 了解更多

  • 我需要12次外循环,每个外循环1次内循环 例如: 等 但现在我的内循环在第一次迭代的外循环上运行。 请帮助我如何使用for循环执行此操作。

  • 问题内容: 和别的: 两者都不起作用(强制关闭应用程序)。我可以尝试其他哪些选择? 问题答案: 您的代码失败,因为您在后台线程中执行睡眠,但是显示数据必须在UI线程中执行。 您必须从runOnUiThread(Runnable)运行displayData或定义处理程序并将消息发送给它。 例如: