0

我正在调用的程序遇到问题。

该过程有 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

你能帮助我吗?

问候,

埃尔卡斯

4

1 回答 1

1

我怀疑您的问题是 MySQL不支持 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构造一个用于组合表的INSERT ... SELECT语句来省去第一个游标:UNION

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语句中;实际上,该语句可能只准备一次第一个游标的迭代并在第二个游标的每次迭代中使用不同的值执行)。

于 2012-05-25T20:35:58.593 回答