MySQL 原生游標只支援靜態 SQL,若需根據參數動態構建查詢(如動態表名、動態 WHERE 條件),可結合預處理語句與視圖繞過限制。本文示範完整實現流程。
PREPARE、EXECUTE 建立並執行動態視圖。-- 建立測試表與資料
CREATE TABLE webuser (username VARCHAR(10));
INSERT INTO webuser VALUES ('a1'),('a2'),('a3'),('b1'),('b2'),('b3');
-- 建立存儲過程
DROP PROCEDURE IF EXISTS dynamic_cursor;
DELIMITER //
CREATE PROCEDURE dynamic_cursor (IN p_name VARCHAR(10))
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE v_username VARCHAR(10);
-- 1. 宣告游標指向視圖(視圖稍後動態建立)
DECLARE cur CURSOR FOR SELECT username FROM webuser_view;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
-- 2. 動態建立/重建視圖
DROP VIEW IF EXISTS webuser_view;
SET @sqlstr = CONCAT("CREATE VIEW webuser_view AS SELECT username FROM webuser WHERE username LIKE '", p_name, "%'");
PREPARE stmt FROM @sqlstr;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- 3. 遍歷游標
OPEN cur;
read_loop: LOOP
FETCH cur INTO v_username;
IF done THEN LEAVE read_loop; END IF;
SELECT v_username AS `動態查詢結果`;
END LOOP;
CLOSE cur;
END//
DELIMITER ;
-- 測試呼叫
CALL dynamic_cursor('a');
webuser_view),故每次呼叫前必須 DROP VIEW IF EXISTS 再重建。p_name 進行轉義或驗證(如 QUOTE())。| 方案 | 優點 | 缺點 |
|---|---|---|
| 動態視圖 + 游標 | 純 SQL 實現,邏輯封裝在 DB | DDL 開銷大,不適合高頻呼叫 |
| 應用層拼接 SQL | 靈活、效能好、易除錯 | 業務邏輯分散,需防注入 |
| 臨時表 + 游標 | 避免 DDL 鎖,支援複雜中間結果 | 需手動管理臨時表生命週期 |
適用場景: 報表類、批次處理、低頻呼叫的動態查詢封裝。高併發核心業務請優先考慮應用層方案。