sql >> データベース >  >> RDS >> Mysql

2つのプロシージャのそれぞれが独自のテーブルにデータを入力するのではなく、2つのプロシージャを1つに組み合わせて1つのテーブルにデータを入力するにはどうすればよいですか?

    右;ここにあるものを見てみましょう。

    まず、コードを次のようにブロックする必要があります。

    variable declarations
    cursor declarations
    handler declarations
    everything else
    

    つまり、DECLARE CURSOR c2 必須 DECLARE CURSOR c1の間に表示されます およびDECLARE CONTINUE HANDLER 。また、必要なCONTINUE HANDLERは1つだけです。 宣言の時点から手順の最後まで有効になるためです。

    次はステートメントです

    INSERT INTO ip_ER_subtotal
        SELECT Starting_Pitcher, Game_Date, Game_Number, innings_pitched, 0.0
            FROM starting_pitchers_game_log;
    

    SELECTの名前付き列 句は、選択する列です。 ない 挿入しているもの したがって、テーブルstarting_pitchers_game_logの列である必要があります。 。また、列がstarting_pitchers_game_logからコピーされていないため (つまり、ip_totaler_total およびera )すべてデフォルト値があり、INSERTで列リストを使用できます そのような声明:

    INSERT INTO pitcher_stats_temp
        (Starting_Pitcher, Game_Date, Game_Number, innings_pitched, er)
      SELECT pitcher_id, game_date, game_seq, innings_pitched, runs
        FROM starting_pitchers_game_log;
    

    これにより、入力が節約され、実際に値を挿入している列が文書化され、INSERTが分離されます。 ソーステーブルとターゲットテーブルの列の物理的な順序からのステートメント。

    次に、CURSOR c1を終了したら ループ、テーブルを切り捨てないでください または、今行ったすべての作業が失われます。 TRUNCATE TABLE 現在テーブルにあるすべての行を削除し、前の実行の結果をクリアするためにここで使用されます。

    最後に、2つのループには異なるラベルを付ける必要があります(例:fetch_loop_1)。 およびfetch_loop_2 。また、accumをリセットする必要があります およびend_of_cursor 2番目のループに入る前。ただし、この場合、1つのカーソルですべてを1つのループで実行できるため、コードが単純になり、保守が容易になると思います。

    完全な手順は次のとおりです。

    DROP PROCEDURE IF EXISTS pitcher_stats_era;
    
    DELIMITER $$
    
    CREATE PROCEDURE pitcher_stats_era()
      BEGIN
        DECLARE pit_id CHAR(10);
        DECLARE gdate DATE;
        DECLARE seq INT;
        DECLARE in_pit REAL;
        DECLARE er INT;
        DECLARE accum_ip REAL;
        DECLARE accum_er INT;
        DECLARE earned_run_avg REAL;
        DECLARE prev_year YEAR(4);
        DECLARE end_of_cursor BOOLEAN;
    
        DECLARE no_table CONDITION FOR SQLSTATE '42S02';
    
        DECLARE c1 CURSOR FOR
          SELECT pitcher_id, game_date, game_seq, innings_pitched, earned_runs
            FROM pitcher_stats_temp
            ORDER BY pitcher_id, game_date, game_seq;
    
        DECLARE CONTINUE HANDLER FOR NOT FOUND
          SET end_of_cursor := TRUE;
    
        DECLARE EXIT HANDLER FOR no_table
        BEGIN
          SIGNAL no_table
            SET MESSAGE_TEXT = "Work table not initialized. Please call pitcher_stats_reset() before continuing",
            MYSQL_ERRNO = 1146;
        END;
    ------------------------------------------------------------------
    -- The following steps are now performed by pitcher_stats_reset()
    ------------------------------------------------------------------
    --  TRUNCATE TABLE ip_subtotal;  -- Clear our work table for a new run
        -- Copy data from main table into work table
    --  INSERT INTO ip_subtotal
    --      (pitcher_id, game_date, game_seq, innings_pitched, earned_runs)
    --    SELECT pitcher_id, game_date, game_seq,
    --        IFNULL(innings_pitched, 0),  -- replace NULL with 0, if
    --        IFNULL(runs, 0)              --   column not initialized
    --      FROM starting_pitchers_game_log;
    ---------------------------------------------------------------------
    
        SET end_of_cursor := FALSE;  -- reset
        SET prev_year := 0;          -- reset control-break
    
        OPEN c1;
    
        fetch_loop: LOOP
          FETCH c1 INTO pit_id, gdate, seq, in_pit, er;
          IF end_of_cursor THEN
            LEAVE fetch_loop;
          END IF;
    
          -- check control-break conditions
          IF YEAR(gdate) != prev_year THEN
            SET accum_ip := 0.0;
            SET accum_er := 0;
            SET prev_year := YEAR(gdate);
          END IF;
    
          SET accum_ip := accum_ip + in_pit;
          SET accum_er := accum_er + er;
          IF accum_er = 0 THEN  -- prevent divide-by-zero
            SET earned_run_avg := 0;
          ELSE
            SET earned_run_avg := (accum_ip / accum_er) * 9;
          END IF;
    
          UPDATE pitcher_stats_temp
            SET ip_total = accum_ip,
                er_total = accum_er,
                std_era = earned_run_avg
            WHERE pitcher_id = pit_id
              AND game_date = gdate
              AND game_seq = seq;
    
        END LOOP;
    
        CLOSE c1;
      END
    $$
    DELIMITER ;
    

    それでうまくいくはずです。誰かがバグを見つけたら、ぜひ指摘してください。

    編集:ソーステーブルからのヌルから保護する方法と、ERA計算でゼロ除算を回避する方法を説明するコードを追加しました。

    編集:自分の混乱を減らすために、元の列とテーブルの名前に戻しました。

    編集:コードが変更され、新しいストアドプロシージャを使用して列を作業テーブルに追加するにはどうすればよいですか




    1. 変数をトリガーに渡す

    2. ORA028513DG4ODBCエラーの調査

    3. MariaDBの時刻または日時の値にAM/PMを追加する方法

    4. php-mysqlスクリプトが失敗したときに詳細なエラーレポートを取得する方法は?