首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

MySQL 存儲過程中 Cursor 游標完整實戰教程

     編輯:MySQL 綜合教學

業務場景

將學生表 (t_student) 和成績表 (t_stu_score) 中符合條件的數據 (出生日期 ≥ 1990-03-01 且分數 ≥ 參數閾值) 聚合插入到詳情表 (t_stu_detail)。

表結構定義


CREATE TABLE `t_student` (
  `stuNum` INT(11) NOT NULL AUTO_INCREMENT,
  `stuName` VARCHAR(20) DEFAULT NULL,
  `birthday` DATE DEFAULT NULL,
  PRIMARY KEY (`stuNum`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `t_stu_score` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `stuNum` INT(11) DEFAULT NULL,
  `score` DECIMAL(6,2) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `FK_t_stu_score` (`stuNum`),
  CONSTRAINT `FK_t_stu_score` FOREIGN KEY (`stuNum`) REFERENCES `t_student` (`stuNum`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `t_stu_detail` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `stuName` VARCHAR(20) DEFAULT NULL,
  `score` DECIMAL(6,2) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

存儲過程完整代碼


DELIMITER $$
CREATE PROCEDURE `proc_AddStuDetail`(IN p_score DECIMAL(6,2))
BEGIN
    -- 變量聲明 (必須在開頭)
    DECLARE v_stuNum INT;
    DECLARE v_stuName VARCHAR(20);
    DECLARE v_birthday DATE;
    DECLARE v_score DECIMAL(6,2);
    DECLARE done INT DEFAULT 0;  -- 結束標記,初始化為 0

    -- 1. 聲明游標 (SELECT 查詢)
    DECLARE stuCursor CURSOR FOR
        SELECT stuNum, stuName, birthday FROM t_student;

    -- 2. 聲明 NOT FOUND 異常處理器 (游標讀取結束時觸發)
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

    -- 3. 打開游標
    OPEN stuCursor;

    -- 4. 循環讀取
    stuLoop: LOOP
        -- 取數據到變量
        FETCH stuCursor INTO v_stuNum, v_stuName, v_birthday;

        -- 判斷是否結束
        IF done = 1 THEN
            LEAVE stuLoop;
        END IF;

        -- 業務邏輯
        IF v_birthday >= '1990-03-01' THEN
            SELECT score INTO v_score FROM t_stu_score WHERE stuNum = v_stuNum;
            IF v_score >= p_score THEN
                INSERT INTO t_stu_detail VALUES (NULL, v_stuName, v_score);
            END IF;
        END IF;
    END LOOP stuLoop;

    -- 5. 關閉游標 (釋放資源,必須執行)
    CLOSE stuCursor;
END$$
DELIMITER ;

調用測試


CALL proc_AddStuDetail(86);

關鍵知識點總結

  1. 聲明順序嚴格:變量 → 條件/處理器 → 游標 → 處理器 (MySQL 要求)
  2. NOT FOUND 處理器:DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; 是游標循環退出的核心機制
  3. FETCH INTO:列順序、類型、數量必須與游標 SELECT 完全一致
  4. 游標生命週期:OPEN → FETCH 循環 → CLOSE。異常退出也需確保 CLOSE (可用 DECLARE EXIT HANDLER 兜底)
  5. 性能提示:游標屬於行級處理,大數據量極慢。優先考慮集合操作 (INSERT ... SELECT ... JOIN) 或應用層批次處理。此例可優化為單條 SQL:
    
    INSERT INTO t_stu_detail (stuName, score)
    SELECT s.stuName, sc.score
    FROM t_student s
    JOIN t_stu_score sc ON s.stuNum = sc.stuNum
    WHERE s.birthday >= '1990-03-01' AND sc.score >= p_score;
    
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved