2012-05-25 2 views
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 

Помогите мне?

С уважением,

Elkas

ответ

1

Я подозреваю, ваша проблема в том, что MySQL does not supportCREATE 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, действительно, это утверждение может иметь был подготовлен только один раз на итерацию первого курсора и выполнялся с разными значениями на каждой итерации второго курсора).

+0

Извините за ответ прямо сейчас, у меня не было надлежащего подключения к интернету в выходные дни. Я не знаю, есть ли проблема с представлением, потому что на первой итерации первого цикла все это ОК. Только во втором он останавливается в начале процесса (останавливается при выборе данных, idempregado, idsociedade, nif, tipo из temp_agencia_view; он возвращает 0 результатов). Но я постараюсь использовать подход. Дайте мне всего пару часов. – Elkas

+0

Абу параллелизм, если я правильно его понимаю, это будет без проблем, потому что эта таблица будет использоваться только в процедуре.Никакой другой (в коде или пользователях) не знает о существовании этого. – Elkas

+0

Спасибо, помощник. Это была проблема. Может быть, вы ответите мне на этот вопрос сейчас. Почему на 1-й итерации все было хорошо, а во втором я не получил никаких данных? – Elkas

Смежные вопросы