我正在调用我正在调用的程序。
程序有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
答案 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
语句;实际上语句只能在第一个游标的每次迭代中准备一次,并在第二个游标的每次迭代时使用不同的值执行。)