文件首頁
MySQL 9.0 參考手冊
相關文件 下載本手冊
PDF (美式信紙) - 40.0Mb
PDF (A4) - 40.1Mb
Man Pages (TGZ) - 258.2Kb
Man Pages (Zip) - 365.3Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


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

15.5 預處理語句

MySQL 9.0 支援伺服器端預處理陳述式。此支援利用了高效的客戶端/伺服器二進制協議。使用帶有參數值佔位符的預處理陳述式具有以下優點:

  • 每次執行陳述式時,減少了解析陳述式的額外開銷。通常,資料庫應用程式會處理大量幾乎相同的陳述式,只有在查詢和刪除的 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
{CREATE | ALTER | DROP } EVENT
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.9 節,「預存程式的限制」中。

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

使用預處理陳述式時,佔位符可以用於 LIMIT 子句的引數。請參閱第 15.2.13 節,「SELECT 陳述式」

包含事件 DDL 的預處理陳述式不支援佔位符。嘗試在此類陳述式中使用佔位符會被 PREPARE 拒絕,並顯示 ERROR 6413 (HY000): 動態參數只能在 DML 陳述式中使用。相反地,您可以透過將包含事件 SQL 的文字組裝在預存程序的主體中,並將 SQL 陳述式的任何變數部分作為預存程序的 IN 參數傳遞,以可重複使用的方式執行此操作;然後,您可以使用 PREPARE 陳述式(也在預存程序的主體內)準備已組裝的文字,然後使用所需的參數值叫用程序。請參閱第 15.1.13 節,「CREATE EVENT 陳述式」以取得範例。

在與 PREPAREEXECUTE 一起使用的預處理 CALL 陳述式中,MySQL 9.0 開始提供 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 陳述式」