首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL 預存程序動態 SQL 實戰:PREPARE/EXECUTE 變數限制與表名參數化解決方案

     編輯:MySQL 資料庫相關知識

核心限制總結

標準動態 SQL 模板

DROP PROCEDURE IF EXISTS `up_common_select`;
CREATE PROCEDURE `up_common_select`(IN t_name VARCHAR(64))
BEGIN
    DECLARE v_sql VARCHAR(500);
    
    -- 1. 組裝 SQL 字串(解決表名參數化)
    SET v_sql = CONCAT('SELECT * FROM `', t_name, '`');
    
    -- 2. 必須轉給 @session 變數
    SET @v_sql = v_sql;
    
    -- 3. PREPARE / EXECUTE / DEALLOCATE
    PREPARE stmt FROM @v_sql;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
END;

-- 呼叫
CALL up_common_select('admin_authority');

進階:帶參數的動態查詢

CREATE PROCEDURE `search_users`(
    IN tbl VARCHAR(64),
    IN keyword VARCHAR(100),
    IN lim INT
)
BEGIN
    SET @sql = CONCAT('SELECT * FROM `', tbl, '` WHERE name LIKE ? LIMIT ?');
    SET @kw = CONCAT('%', keyword, '%');
    SET @lim = lim;
    
    PREPARE stmt FROM @sql;
    EXECUTE stmt USING @kw, @lim;  -- 必須用 @變數
    DEALLOCATE PREPARE stmt;
END;

安全防注入檢查清單

  1. 表名/欄位名:白名單驗證,不可直接拼接用戶輸入
  2. 值參數:務必用 PREPARE + USING,絕不拼接
  3. 識別符反引號:CONCAT('`', REPLACE(identifier, '`', ''), '`')
  4. 限制 max_prepared_stmt_count 防止洩漏

常見錯誤與修正

限制說明版本
表名/欄位名不可作參數PREPARE stmt FROM 'SELECT * FROM ?' 報錯5.0.24+ 仍不支援
EXECUTE USING 僅接受 @session 變數DECLARE 區域變數、參數變數皆不可用所有版本
PREPARE 需 5.0.13+存儲程序中才支援動態 SQL5.0.13+

效能提示

  • 動態 SQL 無法使用查詢快取(已移除)
  • 頻繁 PREPARE 產生解析開銷,熱點路徑改用固定 SQL
  • PREPARE 會話級持久,連線池復用時注意清理
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
錯誤寫法正確寫法
PREPARE stmt FROM 'SELECT * FROM ?';SET @sql = CONCAT('SELECT * FROM `', @tbl, '`'); PREPARE stmt FROM @sql;
EXECUTE stmt USING v_param; (區域變數)SET @v_param = v_param; EXECUTE stmt USING @v_param;
忘記 DEALLOCATE必須成對 DEALLOCATE PREPARE stmt;