存储过程多个循环仅获取第一个循环数据

时间:2012-05-25 18:26:05

标签: mysql stored-procedures

我正在调用我正在调用的程序。

程序有2个循环,一个用于连接到同一网络中的其他数据库,另一个用于从每个连接获取数据,但问题是它只从第一个连接获取第一个数据包。我不确定,但也许我在第二个循环中做错了什么,忘记了什么。这是我第二次做这样的事情,这是第一次让它复杂化。

以下是程序的代码。

CREATE PROCEDURE `firians`.`sincronizarAgencias` ()
BEGIN
declare nomeAgencia varchar(255);
declare ultimaAgencia int default false;
declare terminouPicagens int default false;

declare agenciasCur cursor for select ip from agencia;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET ultimaAgencia = TRUE;

open agenciasCur;
nomeAgenciasLoop: LOOP

    FETCH agenciasCur INTO nomeAgencia;

    IF ultimaAgencia THEN
        close agenciasCur; 
        LEAVE nomeAgenciasLoop;
    END IF;

    SELECT nomeAgencia;

    DROP VIEW IF EXISTS temp_agencia_view;
    SET @query = CONCAT('CREATE VIEW temp_agencia_view as select data, idempregado, idsociedade, nif, tipo from `', nomeAgencia, '`'); 
    select @query; 
    PREPARE stmt from @query; 
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;

    blocoPicagens: BEGIN
        declare newData DATETIME;
        declare newIdEmpregado VARCHAR(45);
        declare newIdSociedade bigint(20);
        declare newNif varchar(15);
        declare newTipo varchar(45);

        declare ultimaPicagem int default false;

        -- SELECT data, idempregado, idsociedade, nif, tipo from temp_agencia_view;

        DECLARE picagensCursor cursor for select data, idempregado, idsociedade, nif, tipo from temp_agencia_view;
        DECLARE CONTINUE HANDLER FOR NOT FOUND SET ultimaPicagem := TRUE;

        open picagensCursor;
        picagensLoop: LOOP
            fetch picagensCursor into newData, newIdEmpregado, newIdSociedade, newNif, newTipo;

            IF ultimaPicagem THEN
                -- SET ultimaPicagem := false;
                close picagensCursor;
                DROP VIEW IF EXISTS temp_agencia_view; 
                LEAVE picagensLoop;
            END IF;

            INSERT INTO `firians`.`assiduidade`(`data`,`idempregado`,`idsociedade`,`tipo`,`nif`)
            VALUES
            (newData, newIdEmpregado, newIdSociedade, newTipo, newNif);

            INSERT INTO `firians`.`assiduidadebackup`(`data`,`idempregado`,`idsociedade`,`tipo`,`nif`)
            VALUES
            (newData, newIdEmpregado, newIdSociedade, newTipo, newNif);

            set @updateRowQuery = CONCAT('DELETE FROM `', nomeAgencia,'` WHERE idempregado = ', newIdEmpregado, ' AND idsociedade = ', newIdSociedade, ' AND tipo = ', newTipo, ' AND data LIKE \'', newData, "'"); 
            select @updateRowQuery;
            PREPARE stmtUpdate from @updateRowQuery; 
            EXECUTE stmtUpdate; 
            DEALLOCATE PREPARE stmtUpdate;

        END LOOP picagensLoop;

    DROP VIEW IF EXISTS temp_agencia_view;
        -- select * from temp_agencia_view;           
    END blocoPicagens;

END LOOP nomeAgenciasLoop;

DROP VIEW IF EXISTS temp_agencia_view;
END

你能帮助我吗?

此致

Elkas

1 个答案:

答案 0 :(得分:1)

我怀疑你的问题是来自准备好的声明中的MySQL does not support CREATE VIEW。您可以改为使用临时表:

SET @query = CONCAT('
  CREATE TEMPORARY TABLE temp_agencia_tbl
    select data, idempregado, idsociedade, nif, tipo from `', nomeAgencia, '`
');

然而,这种方法看起来有点矫枉过正,因为可以在预准备语句中使用INSERT ... SELECT语法来完全避免第二个游标:

SET @q1 = CONCAT('
  INSERT INTO firians.assiduidade
          (data, idempregado, idsociedade, tipo, nif)
    SELECT data, idempragado, idsociedade, tipo, nif FROM `', nomeAgencia, '`
');
SET @q2 = CONCAT('
  INSERT INTO firians.assiduidadebackup
          (data, idempregado, idsociedade, tipo, nif)
    SELECT data, idempragado, idsociedade, tipo, nif FROM `', nomeAgencia, '`
');
SET @q3 = CONCAT('TRUNCATE `', nomeAgencia, '`');

即使这个仍然看起来有点矫枉过正,因为人们也可以通过使用GROUP_CONCAT来构建一个使用{{3}的INSERT ... SELECT语句来省去第一个游标。组合表:

SELECT
  CONCAT('
    INSERT INTO firians.assiduidade
            (data, idempregado, idsociedade, tipo, nif)'
  , GROUP_CONCAT('
      SELECT data, idempregado, idsociedade, tipo, nif FROM `', ip, '`'
      SEPARATOR ' UNION ALL ')
  ) INTO @q1
, CONCAT('
    INSERT INTO firians.assiduidadebackup
            (data, idempregado, idsociedade, tipo, nif)'
  , GROUP_CONCAT('
      SELECT data, idempregado, idsociedade, tipo, nif FROM `', ip, '`'
      SEPARATOR ' UNION ALL ')
  ) INTO @q2
, CONCAT('
    DELETE FROM ', GROUP_CONCAT('`', ip, '`'), '
          USING ', GROUP_CONCAT('`', ip, '`')
  ) INTO @q3
FROM agencia;

但是,尽管如此,以这种方式使用变量表通常表明数据库设计不佳。您可能会发现,组合所有不同记录的单个表(使用附加列来指示任何区分,例如数据源自哪个表)将更加容易,而不是具有相似模式的多个表。例如,上面将简单地简化为:

INSERT INTO firians.assiduidade
        (data, idempregado, idsociedade, tipo, nif)
  SELECT data, idempregado, idsociedade, tipo, nif FROM CombinedTable;

INSERT INTO firians.assiduidadebackup
        (data, idempregado, idsociedade, tipo, nif)
  SELECT data, idempregado, idsociedade, tipo, nif FROM CombinedTable;

TRUNCATE CombinedTable;

请注意,我没有在这个答案中解决并发问题,因为它们没有在原始SP中解决;显然,如果并发可能是一个问题,你应该考虑锁定策略,例如在事务中包含这些操作。

值得指出的是,虽然必须像往常一样将SQL标识符连接到预准备语句中,但值可以在执行时传递给预准备语句(例如,进入DELETE语句;实际上语句只能在第一个游标的每次迭代中准备一次,并在第二个游标的每次迭代时使用不同的值执行。)