Mysql游标循环只运行一次

时间:2014-02-26 20:16:20

标签: mysql stored-procedures cursor

我正在使用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 个答案:

答案 0 :(得分:0)

没有以下信息:

  • 表格结构:assessments
  • 功能: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 Fiddle demo

答案 1 :(得分:0)

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

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