2017-06-20 4 views
0

このMySQLプロシージャは、2つのテーブルにループを作成し、tblResultsにデータを準備し、すべてのデータをエラーがなければ大きなテーブルに挿入します。 2つの日付の間に見つかった行。MySQL INSERT INTOテーブルプロシージャ内のanother_tableから選択

問題は、プロシージャが実行する終了した後、私は、この警告受け取ることである:私はtblResultsテーブルに250個の異なる行を有する場合

Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statements writing to a table with an auto-increment column after selecting from another table are unsafe because the order in which rows are retrieved determines what (if any) rows will be written. This order cannot be predicted and may differ on master and the slave.

その結果を、手順250個の同一の行を挿入ファイナルテーブルに入れる。 (tblResultsにある通常の最初または最後の行に、tblResultsからのレコード数を掛けたもの)。

このようなSQLコードを見て:tblResultsに何が含まれているか挿入を取り除くために

BEGIN 
-- DECLARE bDone INT; 

    DECLARE CustomerId INT; 
    DECLARE LocationId INT; 
    DECLARE ContractId INT; 
    DECLARE DatePeriod DATE; 
    DECLARE SerialWeight DOUBLE; 
    DECLARE Serial VARCHAR(150); 
    DECLARE EnergyZone VARCHAR(5); 
    DECLARE ConsDay DATE; 
    DECLARE T0 DOUBLE; 
    DECLARE T1 DOUBLE; 
    DECLARE T2 DOUBLE; 
    DECLARE T3 DOUBLE; 
    DECLARE T4 DOUBLE; 
    DECLARE T5 DOUBLE; 
    DECLARE T6 DOUBLE; 
    DECLARE T7 DOUBLE; 
    DECLARE T8 DOUBLE; 
    DECLARE T9 DOUBLE; 
    DECLARE T10 DOUBLE; 
    DECLARE T11 DOUBLE; 
    DECLARE T12 DOUBLE; 
    DECLARE T13 DOUBLE; 
    DECLARE T14 DOUBLE; 
    DECLARE T15 DOUBLE; 
    DECLARE T16 DOUBLE; 
    DECLARE T17 DOUBLE; 
    DECLARE T18 DOUBLE; 
    DECLARE T19 DOUBLE; 
    DECLARE T20 DOUBLE; 
    DECLARE T21 DOUBLE; 
    DECLARE T22 DOUBLE; 
    DECLARE T23 DOUBLE; 
    DECLARE QtyEstimated DECIMAL(20,4); 

    DECLARE QtyMeasured DECIMAL(20,4); 
    DECLARE POD VARCHAR(50); 

    DECLARE Quantity DECIMAL(20,4); 
    DECLARE LocationCode VARCHAR(50); 

    DECLARE rCustomerId INT; 
    DECLARE rLocationId INT; 
    DECLARE rContractId INT; 
    DECLARE rDate DATE; 
    DECLARE rTime INT; 
    DECLARE rQtyEstimated DECIMAL(20,4); 
    DECLARE rQtyPredicted DECIMAL(20,4); 
    DECLARE rQtyMeasured DOUBLE; 
    DECLARE rCreateUser INT; 
    DECLARE rUpdateUser INT; 
    DECLARE rFirmaId INT; 



    DECLARE curs CURSOR FOR 

    select 
     ec.CustomerId, 
     ec.LocationId, 
     ec.Id as ContractId, 
     els.Date as DatePeriod, 
     els.SerialWeight, 
     ets.Serial, 
     ets.EnergyZone, 
     ets.Date as ConsDay, 
     ets.T0, 
     ets.T1, 
     ets.T2, 
     ets.T3, 
     ets.T4, 
     ets.T5, 
     ets.T6, 
     ets.T7, 
     ets.T8, 
     ets.T9, 
     ets.T10, 
     ets.T11, 
     ets.T12, 
     ets.T13, 
     ets.T14, 
     ets.T15, 
     ets.T16, 
     ets.T17, 
     ets.T18, 
     ets.T19, 
     ets.T20, 
     ets.T21, 
     ets.T22, 
     ets.T23, 
     CASE substr(els.Date, 6, 2) 
     WHEN '01' THEN ec.Estimated1 
     WHEN '02' THEN ec.Estimated2 
     WHEN '03' THEN ec.Estimated3 
     WHEN '04' THEN ec.Estimated4 
     WHEN '05' THEN ec.Estimated5 
     WHEN '06' THEN ec.Estimated6 
     WHEN '07' THEN ec.Estimated7 
     WHEN '08' THEN ec.Estimated8 
     WHEN '09' THEN ec.Estimated9 
     WHEN '10' THEN ec.Estimated10 
     WHEN '11' THEN ec.Estimated11 
     WHEN '12' THEN ec.Estimated12 
     END as QtyEstimated 
    from EnergyLocationSeries els 
    left join EnergyTimeSeries ets ON ets.Serial = els.Serial and concat(substr(ets.Date, 1, 7), '-01') = els.Date 
    left join EnergyLocation el ON el.Code2 = els.LocationCode 
    left join EnergyContract ec ON (el.Id = ec.LocationId AND el.Codep = '') OR (ec.LocationId = (SELECT max(Id) FROM EnergyLocation WHERE Code2 = el.Codep) AND Codep !='') -- AND ec.`Status` != 'Reziliat' 
    where els.Date = MTH and els.EnergyZone = ZONE 
    order by ets.Date ASC LIMIT 10; 


    DECLARE pods_cursor CURSOR FOR 

     SELECT els.LocationCode, els.Quantity 
     FROM EnergyLocation el 
     RIGHT JOIN EnergyLocationSeries els ON els.LocationCode = el.Code2 OR els.LocationCode = el.Codep 
     LEFT JOIN EnergyContract ec on ec.LocationId = el.Id 
     WHERE el.Code2 IS NULL; 



    DECLARE result CURSOR FOR 
     SELECT `CustomerId`, `LocationId`, `ContractId`, `Date`, `Time`, `QtyEstimated`, `QtyPredicted`, `QtyMeasured`, `CreateUser`, `UpdateUser`, `FirmaId` 
     FROM tblResults ORDER BY CustomerId, ContractId ASC; 


    DROP TABLE IF EXISTS tblResultsErrors; 
    CREATE TABLE IF NOT EXISTS tblResultsErrors (
    `POD` INT(11) NULL DEFAULT NULL, 
    `QtyMeasured` DECIMAL(20,4) NULL DEFAULT NULL 
); 



    DROP TABLE IF EXISTS tblResults; 
    CREATE TABLE IF NOT EXISTS tblResults (
    `CustomerId` INT(11) NULL DEFAULT NULL, 
    `LocationId` INT(11) NULL DEFAULT NULL, 
    `ContractId` INT(11) NULL DEFAULT NULL, 
    `Date` DATE NULL DEFAULT NULL, 
    `Time` SMALLINT(6) NULL DEFAULT NULL, 
    `QtyEstimated` DECIMAL(20,4) NULL DEFAULT NULL, 
    `QtyPredicted` DECIMAL(20,4) NULL DEFAULT NULL, 
    `QtyMeasured` DOUBLE NULL DEFAULT NULL, 
    `CreateUser` VARCHAR(32) NULL DEFAULT NULL, 
    `UpdateUser` VARCHAR(32) NULL DEFAULT NULL, 
    `FirmaId` INT(11) NULL DEFAULT NULL 
); 





    OPEN curs; 
    BEGIN 
     DECLARE bDone INT; 
     DECLARE CONTINUE HANDLER FOR NOT FOUND SET bDone = 1; 

     SET bDone = 0; 
     REPEAT 
     FETCH curs INTO  
      CustomerId, 
      LocationId, 
      ContractId, 
      DatePeriod, 
      SerialWeight, 
      Serial, 
      EnergyZone, 
      ConsDay, 
      T0, 
      T1, 
      T2, 
      T3, 
      T4, 
      T5, 
      T6, 
      T7, 
      T8, 
      T9, 
      T10, 
      T11, 
      T12, 
      T13, 
      T14, 
      T15, 
      T16, 
      T17, 
      T18, 
      T19, 
      T20, 
      T21, 
      T22, 
      T23, 
      QtyEstimated; 

     IF bDone = 0 THEN 

      INSERT INTO tblResults VALUES 
       (CustomerId,LocationId,ContractId,ConsDay,1,QtyEstimated,0,(T0 * (SerialWeight/100)),'root','root',0), 
       (CustomerId,LocationId,ContractId,ConsDay,2,QtyEstimated,0,(T1 * (SerialWeight/100)),'root','root',0), 
       (CustomerId,LocationId,ContractId,ConsDay,3,QtyEstimated,0,(T2 * (SerialWeight/100)),'root','root',0), 
       (CustomerId,LocationId,ContractId,ConsDay,4,QtyEstimated,0,(T3 * (SerialWeight/100)),'root','root',0), 
       (CustomerId,LocationId,ContractId,ConsDay,5,QtyEstimated,0,(T4 * (SerialWeight/100)),'root','root',0), 
       (CustomerId,LocationId,ContractId,ConsDay,6,QtyEstimated,0,(T5 * (SerialWeight/100)),'root','root',0), 
       (CustomerId,LocationId,ContractId,ConsDay,7,QtyEstimated,0,(T6 * (SerialWeight/100)),'root','root',0), 
       (CustomerId,LocationId,ContractId,ConsDay,8,QtyEstimated,0,(T7 * (SerialWeight/100)),'root','root',0), 
       (CustomerId,LocationId,ContractId,ConsDay,9,QtyEstimated,0,(T8 * (SerialWeight/100)),'root','root',0), 
       (CustomerId,LocationId,ContractId,ConsDay,10,QtyEstimated,0,(T9 * (SerialWeight/100)),'root','root',0), 
       (CustomerId,LocationId,ContractId,ConsDay,11,QtyEstimated,0,(T10 * (SerialWeight/100)),'root','root',0), 
       (CustomerId,LocationId,ContractId,ConsDay,12,QtyEstimated,0,(T11 * (SerialWeight/100)),'root','root',0), 
       (CustomerId,LocationId,ContractId,ConsDay,13,QtyEstimated,0,(T12 * (SerialWeight/100)),'root','root',0), 
       (CustomerId,LocationId,ContractId,ConsDay,14,QtyEstimated,0,(T13 * (SerialWeight/100)),'root','root',0), 
       (CustomerId,LocationId,ContractId,ConsDay,15,QtyEstimated,0,(T14 * (SerialWeight/100)),'root','root',0), 
       (CustomerId,LocationId,ContractId,ConsDay,16,QtyEstimated,0,(T15 * (SerialWeight/100)),'root','root',0), 
       (CustomerId,LocationId,ContractId,ConsDay,17,QtyEstimated,0,(T16 * (SerialWeight/100)),'root','root',0), 
       (CustomerId,LocationId,ContractId,ConsDay,18,QtyEstimated,0,(T17 * (SerialWeight/100)),'root','root',0), 
       (CustomerId,LocationId,ContractId,ConsDay,19,QtyEstimated,0,(T18 * (SerialWeight/100)),'root','root',0), 
       (CustomerId,LocationId,ContractId,ConsDay,20,QtyEstimated,0,(T19 * (SerialWeight/100)),'root','root',0), 
       (CustomerId,LocationId,ContractId,ConsDay,21,QtyEstimated,0,(T20 * (SerialWeight/100)),'root','root',0), 
       (CustomerId,LocationId,ContractId,ConsDay,22,QtyEstimated,0,(T21 * (SerialWeight/100)),'root','root',0), 
       (CustomerId,LocationId,ContractId,ConsDay,23,QtyEstimated,0,(T22 * (SerialWeight/100)),'root','root',0), 
       (CustomerId,LocationId,ContractId,ConsDay,24,QtyEstimated,0,(T23 * (SerialWeight/100)),'root','root',0); 

     END IF; 
     UNTIL bDone END REPEAT; 
    END; 
    CLOSE curs; 



    OPEN pods_cursor; 
    BEGIN 

     DECLARE bDone INT; 
     DECLARE CONTINUE HANDLER FOR NOT FOUND SET bDone = 1; 

     SET bDone = 0; 
     REPEAT 
     FETCH pods_cursor INTO POD, QtyMeasured; 
     IF bDone = 0 THEN 

      INSERT INTO tblResultsErrors VALUES 
      (LocationCode, Quantity); 

     END IF; 

     UNTIL bDone END REPEAT; 

    END; 
    CLOSE pods_cursor; 

    IF NOT EXISTS (SELECT * FROM tblResultsErrors) THEN 
     BEGIN 
      DELETE FROM EnergyIbdRecord WHERE Date BETWEEN MTH AND LAST_DAY(MTH); 

      OPEN result; 
      BEGIN 

       DECLARE bDone INT; 
       DECLARE CONTINUE HANDLER FOR NOT FOUND SET bDone = 1; 

       SET bDone = 0; 
       REPEAT 
       FETCH result INTO rCustomerId,rLocationId,rContractId,rDate,rTime,rQtyEstimated,rQtyPredicted,rQtyMeasured,rCreateUser,rUpdateUser,rFirmaId; 
       IF bDone = 0 THEN 

        INSERT INTO EnergyIbdRecord (`CustomerId`, `LocationId`, `ContractId`, `Date`, `Time`, `QtyEstimated`, `QtyPredicted`, `QtyMeasured`, `CreateUser`, `UpdateUser`, `FirmaId`) 
        VALUES (rCustomerId,rLocationId,rContractId,rDate,rTime,rQtyEstimated,rQtyPredicted,rQtyMeasured,rCreateUser,rUpdateUser,rFirmaId); 

       END IF; 

       UNTIL bDone END REPEAT; 

      END; 
      CLOSE result; 
     END; 
    ELSE 
     BEGIN 
      SELECT * FROM tblResultsErrors; 
     END; 
    END IF; 


END 

任意の提案? おそらく2つの分離された手順を実行する必要がありますか?これはアプローチだろうか?

答えて

0

可能であれば、CURSORsは使用しないでください。 SQLは一度に1行ではなく、一括して処理するように設計されています。

研究は、例えば

INSERT INTO ... SELECT ...; 

CREATE TABLE ... SELECT ...; 

のように構築し、pods_cursorはおそらく経由して排除することができます。(。。痛いRIGHTミキシングとLEFTは、フクロウのように私の頭のスピンになります)

INSERT INTO tblResultsErrors 
     (POD, QtyMeasured) 
    SELECT els.LocationCode, els.Quantity 
     FROM EnergyLocation el 
     RIGHT JOIN EnergyLocationSeries els 
      ON els.LocationCode = el.Code2 OR els.LocationCode = el.Codep 
     LEFT JOIN EnergyContract ec 
      on ec.LocationId = el.Id 
     WHERE el.Code2 IS NULL; 

ONORを使用すると非常に非効率的です。その意図は何ですか?