2012-05-25 3 views
0

부르는 프로 시저에 문제가 있습니다.저장 프로 시저 다중 루프는 첫 번째 루프 데이터 만 가져옵니다.

이 프로 시저에는 동일한 네트워크에있는 다른 데이터베이스에 대한 연결과 각 연결에서 데이터를 가져 오는 두 개의 루프가 있지만 문제는 첫 번째 연결에서 첫 번째 데이터 팩만 가져 오는 것입니다. 나는 잘 모르겠지만 어쩌면 내가 뭔가를 잊어 버리는 두 번째 루프에서 뭔가 잘못하고 있어요. 이것은 내가 그런 일을하고 두 번째로 복잡한 일을하는 첫 번째 시간입니다.

다음은 절차 코드입니다.

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이 준비된 명령문 내에서 의심. 하나는 모두 두 번째 커서 피하기 위해 준비된 명령문 내에서 INSERT ... SELECT 구문을 사용할 수 있습니다로

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

그러나이 방법은 잔인한 것 같아 : 대신 임시 테이블을 사용할 수

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; 

그러나 이런 식으로 변수 테이블을 사용하면 일반적으로 데이터베이스 디자인이 좋지 않음을 알 수 있습니다. 비슷한 스키마를 가진 여러 테이블 대신, 모든 다른 레코드를 결합하는 단일 테이블 (데이터가 시작된 테이블과 같은 차별화를 나타내는 추가 열이 있음)이 상당히 쉬울 것입니다. 예를 들어, 위에서 단순히 줄일 수에 : 그들은 원래 SP에서 해결되지 않은 것처럼 나는이 대답 동시성 문제를 해결하지 않은

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; 

참고; 동시성이 문제가 될 수 있다면 트랜잭션 내에서 이러한 작업을 포괄하는 등의 잠금 전략을 고려해야합니다.

SQL 식별자를 준비된 명령문으로 연결해야하는 반면 실행시 준비된 명령문에 값을 전달할 수 있습니다 (예 : DELETE 문). 첫 번째 커서의 반복마다 한 번만 준비되고 두 번째 커서의 각 반복마다 다른 값으로 실행됩니다.

+0

죄송합니다. 지금 막 주말에 인터넷에 연결되어 있지 않았습니다. 나는 첫 번째 루프의 첫 번째 반복에서 모두 OK이므로 뷰에 문제가 있는지는 알 수 없습니다. 두 번째 경우에만 프로세스 시작시 중지됩니다 (select 데이터, idempregado, idsociedade, nif, tempo에서 가져온 tip_agencia_view에서 중지하고 결과는 0입니다). 그러나 나는 당신이 접근하는 방법을 사용하려고합니다. 몇 시간 만주세요. – Elkas

+0

동시성, 내가 제대로 이해한다면,이 표는 절차에서만 사용되기 때문에 아무런 문제가 없습니다.다른 사람 (코드 또는 사용자)은이 사실을 알고 있지 않습니다. – Elkas

+0

감사합니다. 그 견해가 문제였습니다. 어쩌면 지금이 질문에 대답 할 수 있을지도 몰라. 왜 1 차 반복에서 모두 괜찮 았고 두 번째는 데이터를 얻지 못했습니까? – Elkas