文件首頁
MySQL 8.4 參考手冊
相關文件 下載本手冊
PDF (美國信紙尺寸) - 39.9Mb
PDF (A4) - 40.0Mb
Man Pages (TGZ) - 258.5Kb
Man Pages (Zip) - 365.5Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 參考手冊  /  SQL 語法  /  預處理語句

15.5 預處理語句

MySQL 8.4 提供伺服器端預處理語句的支援。此支援利用高效的客戶端/伺服器二進制協定。使用帶有參數值佔位符的預處理語句具有以下好處:

  • 每次執行語句時,解析語句的開銷較少。通常,資料庫應用程式會處理大量幾乎相同的語句,只有查詢和刪除的 WHERE 子句、更新的 SET 子句,以及插入的 VALUES 子句中的文字或變數值發生變化。

  • 防止 SQL 注入攻擊。參數值可以包含未逸出的 SQL 引號和分隔符號。

以下章節概述了預處理語句的特性:

應用程式中的預處理語句

您可以通過客戶端程式設計介面使用伺服器端預處理語句,包括用於 C 程式的 MySQL C API 客戶端函式庫、用於 Java 程式的 MySQL Connector/J,以及用於使用 .NET 技術的程式的 MySQL Connector/NET。例如,C API 提供了一組構成其預處理語句 API 的函式呼叫。請參閱 C API 預處理語句介面。其他語言介面可以通過連結 C 客戶端函式庫來提供對使用二進制協定的預處理語句的支援,一個例子是 PHP 5.0 和更高版本中提供的 mysqli 擴充功能

SQL 腳本中的預處理語句

另一個可用的預處理語句的 SQL 介面。此介面不像使用預處理語句 API 通過二進制協定那樣有效,但它不需要編程,因為它可以直接在 SQL 層級使用。

  • 當您沒有可用的程式設計介面時,可以使用它。

  • 您可以從任何可以將 SQL 語句發送到伺服器以執行的程式中使用它,例如 mysql 客戶端程式。

  • 即使客戶端正在使用舊版本的客戶端函式庫,您也可以使用它。

預處理語句的 SQL 語法旨在用於以下情況:

  • 在編碼之前,測試預處理語句如何在您的應用程式中運作。

  • 當您無法存取支援預處理語句的程式設計 API 時,使用預處理語句。

  • 以互動方式對預處理語句的應用程式問題進行疑難排解。

  • 建立重現預處理語句問題的測試案例,以便您可以提交錯誤報告。

PREPARE、EXECUTE 和 DEALLOCATE PREPARE 語法

預處理語句的 SQL 語法基於三個 SQL 語法:

以下範例顯示了兩種等效的方式來準備計算三角形斜邊的語句,給定兩邊的長度。

第一個範例顯示了如何通過使用字串文字來提供語句的文字來建立預處理語句。

mysql> PREPARE stmt1 FROM 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
mysql> SET @a = 3;
mysql> SET @b = 4;
mysql> EXECUTE stmt1 USING @a, @b;
+------------+
| hypotenuse |
+------------+
|          5 |
+------------+
mysql> DEALLOCATE PREPARE stmt1;

第二個範例類似,但將語句的文字作為使用者變數提供。

mysql> SET @s = 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
mysql> PREPARE stmt2 FROM @s;
mysql> SET @a = 6;
mysql> SET @b = 8;
mysql> EXECUTE stmt2 USING @a, @b;
+------------+
| hypotenuse |
+------------+
|         10 |
+------------+
mysql> DEALLOCATE PREPARE stmt2;

以下是一個額外的範例,示範如何在執行時選擇要執行查詢的表,方法是將表的名稱儲存為使用者變數。

mysql> USE test;
mysql> CREATE TABLE t1 (a INT NOT NULL);
mysql> INSERT INTO t1 VALUES (4), (8), (11), (32), (80);

mysql> SET @table = 't1';
mysql> SET @s = CONCAT('SELECT * FROM ', @table);

mysql> PREPARE stmt3 FROM @s;
mysql> EXECUTE stmt3;
+----+
| a  |
+----+
|  4 |
|  8 |
| 11 |
| 32 |
| 80 |
+----+

mysql> DEALLOCATE PREPARE stmt3;

預處理語句特定於建立它的會期。如果您在不釋放先前準備的語句的情況下終止會期,伺服器會自動釋放它。

預處理語句對於會期也是全域的。如果您在儲存的常式中建立預處理語句,則該常式結束時不會釋放它。

為了防止同時建立過多的預處理語句,請設定 max_prepared_stmt_count 系統變數。要防止使用預處理語句,請將該值設定為 0。

預處理語句中允許的 SQL 語法

以下 SQL 語法可以用作預處理語句:

ALTER TABLE
ALTER USER
ANALYZE TABLE
CACHE INDEX
CALL
CHANGE MASTER
CHECKSUM {TABLE | TABLES}
COMMIT
{CREATE | DROP} INDEX
{CREATE | RENAME | DROP} DATABASE
{CREATE | DROP} TABLE
{CREATE | RENAME | DROP} USER
{CREATE | DROP} VIEW
DELETE
DO
FLUSH {TABLE | TABLES | TABLES WITH READ LOCK | HOSTS | PRIVILEGES
  | LOGS | STATUS | MASTER | SLAVE | USER_RESOURCES}
GRANT
INSERT
INSTALL PLUGIN
KILL
LOAD INDEX INTO CACHE
OPTIMIZE TABLE
RENAME TABLE
REPAIR TABLE
REPLACE
RESET {MASTER | SLAVE}
REVOKE
SELECT
SET
SHOW BINLOG EVENTS
SHOW CREATE {PROCEDURE | FUNCTION | EVENT | TABLE | VIEW}
SHOW {MASTER | BINARY} LOGS
SHOW {MASTER | SLAVE} STATUS
SLAVE {START | STOP}
TRUNCATE TABLE
UNINSTALL PLUGIN
UPDATE

不支援其他語法。

為了符合 SQL 標準,該標準規定診斷語法不可準備,MySQL 不支援以下內容作為預處理語句:

  • SHOW WARNINGSSHOW COUNT(*) WARNINGS

  • SHOW ERRORSSHOW COUNT(*) ERRORS

  • 包含對 warning_counterror_count 系統變數的任何引用的語法。

一般而言,SQL 預處理語句中不允許的語法在儲存的程式中也不允許。例外情況在 第 27.8 節,「儲存程式的限制」中註明。

當下次執行預處理語句時,會偵測到對預處理語句所參照的表格或視圖的元數據變更,並導致自動重新準備該語句。如需更多資訊,請參閱 第 10.10.3 節,「預處理語句和儲存程式的快取」

當使用預處理語句時,可以使用佔位符作為 LIMIT 子句的參數。請參閱 第 15.2.13 節,「SELECT 語法」

在與 PREPAREEXECUTE 一起使用的預處理 CALL 語法中,從 MySQL 8.4 開始,可以使用 OUTINOUT 參數的佔位符支援。有關範例和早期版本的因應措施,請參閱 第 15.2.1 節,「CALL 語法」。無論版本如何,都可以對 IN 參數使用佔位符。

預處理語句的 SQL 語法不能以巢狀方式使用。也就是說,傳遞給 PREPARE 的語法本身不能是 PREPAREEXECUTEDEALLOCATE PREPARE 語法。

預處理語句的 SQL 語法與使用預處理語句 API 呼叫不同。例如,您不能使用 mysql_stmt_prepare() C API 函式來準備 PREPAREEXECUTEDEALLOCATE PREPARE 語法。

預處理語句的 SQL 語法可以在儲存的程序中使用,但不能在儲存的函式或觸發器中使用。但是,不能將游標用於使用 PREPAREEXECUTE 準備和執行的動態語法。游標的語法在建立游標時進行檢查,因此語法不能是動態的。

預處理語句的 SQL 語法不支援多語句(即,以 ; 字元分隔的單一字串中的多個語法)。

要編寫使用 CALL SQL 語法執行包含預處理語句的儲存程序的 C 程式,必須啟用 CLIENT_MULTI_RESULTS 旗標。這是因為除了程序中執行的語法可能傳回的任何結果集之外,每個 CALL 都會傳回結果以指示呼叫狀態。

當您呼叫 mysql_real_connect() 時,可以啟用 CLIENT_MULTI_RESULTS,可以通過顯式傳遞 CLIENT_MULTI_RESULTS 旗標本身,或者通過隱式傳遞 CLIENT_MULTI_STATEMENTS(同時也會啟用 CLIENT_MULTI_RESULTS)來啟用。如需更多資訊,請參閱 第 15.2.1 節,「CALL 語法」