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

MySQL PREPARE 預處理語句語法詳解:動態 SQL、防注入與存儲過程應用

     編輯:MySQL 資料庫相關知識

三條核心語句


PREPARE stmt_name FROM preparable_sql;      -- 定義
EXECUTE stmt_name [USING @var1, @var2 ...]; -- 執行
{DEALLOCATE | DROP} PREPARE stmt_name;      -- 釋放

關鍵規則

  • stmt_name 不區分大小寫,會話級可見;
  • ? 佔位符僅用於數據值,不可用於表名、列名、關鍵字;
  • ? 無需加引號,即使對應字符串值;
  • 同名 PREPARE 會隱式釋放舊語句;
  • 會話結束自動釋放,建議顯式 DEALLOCATE。

基礎示例


PREPARE ins FROM 'INSERT INTO t(a,b) VALUES(?,?)';
SET @x=1, @y=2;
EXECUTE ins USING @x,@y;
SET @y='foo';
EXECUTE ins USING @x,@y;
DEALLOCATE PREPARE ins;

進階場景

1. 動態構建 SQL(含 LIMIT 參數化,MySQL 5.0.7+)


SET @skip=0, @limit=10;
PREPARE p FROM 'SELECT * FROM t LIMIT ?, ?';
EXECUTE p USING @skip, @limit;

2. 存儲過程中動態執行(MySQL 5.0.13+ 支持)


CREATE PROCEDURE p1(IN id INT, IN name VARCHAR(20))
BEGIN
    DECLARE sql_cmd TEXT DEFAULT 'SELECT * FROM t1';
    IF id IS NOT NULL THEN
        SET sql_cmd = CONCAT(sql_cmd, ' WHERE id=?');
        PREPARE stmt FROM sql_cmd;
        SET @a = id;
        EXECUTE stmt USING @a;
    ELSEIF name IS NOT NULL THEN
        SET sql_cmd = CONCAT(sql_cmd, ' WHERE name LIKE ?');
        PREPARE stmt FROM sql_cmd;
        SET @a = CONCAT(name, '%');
        EXECUTE stmt USING @a;
    END IF;
    DEALLOCATE PREPARE stmt;
END;

3. 防注入原理

參數綁定時,MySQL 將數據值與 SQL 模板分離解析,數據永遠不會被當作 SQL 片段執行,等同於驅動層面的參數化查詢。

支持的 SQL 類型

CREATE TABLE, DELETE, DO, INSERT, REPLACE, SELECT, SET, UPDATE 及大多數 SHOW;不支持 LOCK TABLES、LOAD DATA 等。

注意事項速查

陷阱說明
佔位符用於標識符報錯:PREPARE s FROM 'SELECT ? FROM t' 不合法
重複 PREPARE 同名舊語句被靜默釋放,即使新語句語法錯誤
函數中使用 PREPAREMySQL 5.0.13 前完全禁止,之後僅存儲過程允許
會話結束未 DEALLOCATEServer 自動清理,但長連接應用建議顯式釋放
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved