Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

Làm cách nào để thêm cột vào bảng làm việc bằng thủ tục mới được lưu trữ

Câu hỏi này và câu trả lời của nó, được xây dựng dựa trên câu trả lời cho Làm cách nào để kết hợp hai thủ tục trong một để điền vào một bảng thay vì mỗi trong hai thủ tục điền vào bảng của chính nó? Làm cách nào để thêm một cột tăng dần trên một cột khác trong cùng một bảng? và câu trả lời cho câu hỏi này cần có những thay đổi nhỏ đối với câu trả lời cho hai câu trước, mà tôi sẽ lưu ý khi thích hợp.

Vì các phép tính "thời gian nghỉ ngơi của người ném bóng" và "số lần chạy trung bình kiếm được" là độc lập với nhau, tôi đề xuất một quy trình riêng cho mỗi phép tính. Tuy nhiên, vì kết quả của hai quy trình thường sẽ được sử dụng cùng nhau, tôi đề xuất một bảng đầu chung cho các phép tính và đề xuất tái cấu trúc việc tạo và tập hợp bảng đầu đó vào quy trình thứ ba:

DELIMITER $$

-- DROP PROCEDURE pitcher_stats_reset $$

CREATE PROCEDURE pitcher_stats_reset()
BEGIN
  DROP TEMPORARY TABLE IF EXISTS pitcher_stats_temp;

  CREATE TEMPORARY TABLE pitcher_stats_temp
  (
    pitcher_id      char(10)    NOT NULL,
    game_date       date        NOT NULL,
    game_seq        int         NOT NULL,
    innings_pitched double      DEFAULT 0.0,
    ip_total        double      DEFAULT 0.0,
    earned_runs     INT         DEFAULT 0,
    er_total        INT         DEFAULT 0,
    std_era         DOUBLE      DEFAULT 0.0,
    starter_rest    INT         DEFAULT 0,
    CONSTRAINT pitcher_stats_temp_pk
      PRIMARY KEY (pitcher_id , game_date , game_seq )
  ) ENGINE=InnoDB;

  INSERT INTO pitcher_stats_temp
        (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;
END $$

DELIMITER ;

Phiên bản trước sử dụng một bảng bình thường, liên tục vì tôi chưa quen với việc xử lý các bảng tạm thời của MySQL. Một bảng tạm thời sẽ tự động bị xóa khi người dùng đăng xuất, lấy lại không gian được sử dụng cho dữ liệu dẫn xuất có thể được tạo lại khi cần. Việc giảm và tạo lại bảng tương đương với TRUNCATE ing (ngoại trừ việc bảng không cần tồn tại trước đó) nhanh hơn nhiều so với DELETE vô điều kiện , theo tài liệu MySQL. Tôi đã thực hiện các thay đổi có chú thích thích hợp cho quy trình kiếm được-lần chạy trung bình nữa.

Quy trình tính toán thời gian nghỉ ngơi của các vận động viên ném bóng một lần nữa tuân theo thành ngữ tiêu chuẩn "control-break". Lưu ý rằng chúng tôi đọc bản ghi đầu tiên và thiết lập các trường điều khiển một lần trước khi vào vòng lặp, sau đó trong vòng lặp, chúng tôi kiểm tra điều kiện thoát của mình, xử lý bản ghi "hiện tại", đọc bản ghi "tiếp theo" và lặp lại.

DROP PROCEDURE IF EXISTS pitcher_stats_rest_time;

DELIMITER $$

CREATE PROCEDURE pitcher_stats_rest_time()
  BEGIN
    DECLARE pit_id          CHAR(10);
    DECLARE prev_pit        CHAR(10);
    DECLARE gdate           DATE;
    DECLARE seq             INT;
    DECLARE prev_date       DATE;
    DECLARE rest_days       INT;
    DECLARE end_of_cursor   BOOLEAN;

    DECLARE no_table CONDITION FOR SQLSTATE '42S02';

    DECLARE c1 CURSOR FOR
      SELECT pitcher_id, game_date, game_seq
        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;

    SET end_of_cursor := FALSE;

    -- Read first record and initialize control fields
    OPEN c1;
    FETCH c1 INTO pit_id, gdate, seq;
    SET prev_date := 0;
    SET prev_pit := pit_id;

    fetch_loop: LOOP
      -- Test for end-of-cursor
      IF end_of_cursor THEN
        LEAVE fetch_loop;
      END IF;

      -- Test for change in control fields. If the pitcher changes,
      --  fake a change in the year to trigger the break.
      IF pit_id != prev_pit THEN
        SET prev_date := 0;
      END IF;

      IF YEAR(prev_date) = YEAR(gdate) THEN
        SET rest_days := DATEDIFF(gdate, prev_date);
      ELSE
        SET rest_days := 0;
      END IF;

      UPDATE pitcher_stats_temp
        SET starter_rest = rest_days
        WHERE pitcher_id = pit_id
          AND game_date = gdate
          AND game_seq = seq;

      -- After processing record, update control fields
      SET prev_date := gdate;
      SET prev_pit := pit_id;

      -- Read next record and repeat
      FETCH c1 INTO pit_id, gdate, seq;
    END LOOP;

    CLOSE c1;

  END $$

DELIMITER ;

Đang được sử dụng, pitcher_stats_reset() được gọi đầu tiên, để khởi tạo bảng làm việc. Sau khi hoàn tất, pitcher_stats_era()pitcher_stats_rest_time() có thể được gọi nhiều lần theo bất kỳ thứ tự nào. If pitcher_stats_reset() không được gọi trước, hai thủ tục còn lại sẽ đưa ra lời nhắc lịch sự để làm như vậy.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Node.js không thể xác thực với MySQL 8.0

  2. mysql_insert_id () luôn trả về 0

  3. MySQL / Hibernate - Làm cách nào để gỡ lỗi một kết nối gộp MySQL liên tục bị rớt?

  4. Lỗi khi tạo thủ tục mysql CRUD

  5. Kết xuất MySQL theo truy vấn