相關文件 下載本手冊
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 參考手冊  /  MySQL 9.0 常見問題  /  MySQL 9.0 常見問題:預存程序與函數

A.4 MySQL 9.0 常見問題:預存程序與函數

A.4.1. MySQL 是否支援預存程序與函數?
A.4.2. 在哪裡可以找到 MySQL 預存程序與預存函數的文件?
A.4.3. 是否有 MySQL 預存程序的討論區?
A.4.4. 在哪裡可以找到 ANSI SQL 2003 預存程序規格?
A.4.5. 如何管理預存常式?
A.4.6. 是否有方法可以檢視特定資料庫中的所有預存程序與預存函數?
A.4.7. 預存程序儲存在哪裡?
A.4.8. 是否可以將預存程序或預存函數分組到套件中?
A.4.9. 預存程序可以呼叫另一個預存程序嗎?
A.4.10. 預存程序可以呼叫觸發程序嗎?
A.4.11. 預存程序可以存取表格嗎?
A.4.12. 預存程序是否有陳述式可以引發應用程式錯誤?
A.4.13. 預存程序是否提供例外處理?
A.4.14. MySQL 預存常式可以傳回結果集嗎?
A.4.15. 是否支援預存程序的 WITH RECOMPILE?
A.4.16. 是否有與在 Apache 上使用 mod_plsql 作為閘道來直接與資料庫中的預存程序進行通訊的 MySQL 等效方式?
A.4.17. 我可以將陣列作為輸入傳遞到預存程序嗎?
A.4.18. 我可以將游標作為 IN 參數傳遞到預存程序嗎?
A.4.19. 我可以將游標作為 OUT 參數從預存程序傳回嗎?
A.4.20. 我可以在預存常式中列印出變數的值以進行除錯嗎?
A.4.21. 我可以在預存程序中提交或回復交易嗎?
A.4.22. MySQL 預存程序與函數是否適用於複製?
A.4.23. 在複製來源伺服器上建立的預存程序和函數是否會複製到複本?
A.4.24. 如何複製在預存程序和函數內發生的動作?
A.4.25. 將預存程序與函數一起使用進行複製時,是否有特殊的安全性要求?
A.4.26. 複製預存程序和函數動作有哪些限制?
A.4.27. 上述限制是否會影響 MySQL 執行時間點復原的能力?
A.4.28. 正在採取哪些措施來修正上述限制?

A.4.1.

MySQL 是否支援預存程序與函數?

是。MySQL 支援兩種預存常式類型:預存程序和預存函數。

A.4.2.

在哪裡可以找到 MySQL 預存程序與預存函數的文件?

請參閱第 27.2 節,「使用預存常式」

A.4.3.

是否有 MySQL 預存程序的討論區?

是。請參閱 https://forums.mysql.com/list.php?98

A.4.4.

在哪裡可以找到 ANSI SQL 2003 預存程序規格?

很遺憾,官方規格並未免費提供 (ANSI 讓它們可供購買)。但是,有一些書籍,例如 Peter Gulutzan 和 Trudy Pelzer 合著的 SQL-99 Complete, Really,其中提供了對標準的全面概述,包括預存程序的涵蓋範圍。

A.4.5.

如何管理預存常式?

為預存常式使用清晰的命名方案始終是良好的做法。您可以使用 CREATE [FUNCTION|PROCEDURE]ALTER [FUNCTION|PROCEDURE]DROP [FUNCTION|PROCEDURE]SHOW CREATE [FUNCTION|PROCEDURE] 來管理預存程序。您可以使用 INFORMATION_SCHEMA 資料庫中的 ROUTINES 資料表,取得有關現有預存程序的資訊 (請參閱第 28.3.30 節,「INFORMATION_SCHEMA ROUTINES 資料表」)。

A.4.6.

是否有方法可以檢視特定資料庫中的所有預存程序與預存函數?

是。對於名為 dbname 的資料庫,請在 INFORMATION_SCHEMA.ROUTINES 資料表上使用此查詢

SELECT ROUTINE_TYPE, ROUTINE_NAME
    FROM INFORMATION_SCHEMA.ROUTINES
    WHERE ROUTINE_SCHEMA='dbname';

如需詳細資訊,請參閱第 28.3.30 節,「INFORMATION_SCHEMA ROUTINES 資料表」

預存常式的主體可以使用 SHOW CREATE FUNCTION (適用於預存函數) 或 SHOW CREATE PROCEDURE (適用於預存程序) 來檢視。如需詳細資訊,請參閱第 15.7.7.10 節,「SHOW CREATE PROCEDURE 陳述式」

A.4.7.

預存程序儲存在哪裡?

預存程序儲存在資料字典的 mysql.routinesmysql.parameters 表格中。您無法直接存取這些表格。相反地,請查詢 INFORMATION_SCHEMA 中的 ROUTINESPARAMETERS 表格。請參閱 第 28.3.30 節,「INFORMATION_SCHEMA ROUTINES 表格」 以及 第 28.3.20 節,「INFORMATION_SCHEMA PARAMETERS 表格」

您也可以使用 SHOW CREATE FUNCTION 來取得關於預存函數的資訊,並使用 SHOW CREATE PROCEDURE 來取得關於預存程序的資訊。請參閱 第 15.7.7.10 節,「SHOW CREATE PROCEDURE 語法」

A.4.8.

是否可以將預存程序或預存函數分組到套件中?

不行。MySQL 不支援此功能。

A.4.9.

一個預存程序可以呼叫另一個預存程序嗎?

可以。

A.4.10.

一個預存程序可以呼叫觸發程序嗎?

預存程序可以執行 SQL 語法,例如 UPDATE,這會導致觸發程序被啟用。

A.4.11.

預存程序可以存取表格嗎?

可以。預存程序可以根據需要存取一個或多個表格。

A.4.12.

預存程序是否有引發應用程式錯誤的語法?

有。MySQL 實作了 SQL 標準的 SIGNALRESIGNAL 語法。請參閱 第 15.6.7 節,「條件處理」

A.4.13.

預存程序是否提供例外處理?

MySQL 根據 SQL 標準實作了 HANDLER 定義。詳細資訊請參閱 第 15.6.7.2 節,「DECLARE ... HANDLER 語法」

A.4.14.

MySQL 預存常式可以回傳結果集嗎?

預存程序可以,但是預存函數不可以。如果您在預存程序中執行一般的 SELECT,結果集會直接回傳給用戶端。您需要使用 MySQL 4.1 (或更高版本) 的用戶端/伺服器協定才能運作。這表示,例如在 PHP 中,您需要使用 mysqli 擴充功能,而不是舊的 mysql 擴充功能。

A.4.15.

預存程序是否支援 WITH RECOMPILE

不支援。

A.4.16.

是否有與在 Apache 上使用 mod_plsql 作為閘道,直接與資料庫中的預存程序溝通的 MySQL 等效功能?

MySQL 中沒有等效功能。

A.4.17.

我可以將陣列作為輸入傳遞給預存程序嗎?

不支援。

A.4.18.

我可以將游標作為預存程序的 IN 參數傳遞嗎?

游標僅在預存程序內部可用。

A.4.19.

我可以從預存程序回傳游標作為 OUT 參數嗎?

游標僅在預存程序內部可用。然而,如果您沒有在 SELECT 上開啟游標,結果會直接傳送給用戶端。您也可以使用 SELECT INTO 變數。請參閱 第 15.2.13 節,「SELECT 語法」

A.4.20.

為了除錯目的,我可以在預存常式中列印出變數的值嗎?

可以,您可以在預存程序中執行此操作,但不能在預存函數中執行。如果您在預存程序中執行一般的 SELECT,結果集會直接回傳給用戶端。您必須使用 MySQL 4.1 (或更高版本) 的用戶端/伺服器協定才能運作。這表示,例如在 PHP 中,您需要使用 mysqli 擴充功能,而不是舊的 mysql 擴充功能。

A.4.21.

我可以在預存程序內部提交或回滾交易嗎?

可以。但是,您無法在預存函數內部執行交易操作。

A.4.22.

MySQL 預存程序和函數是否與複製功能一起運作?

可以,在預存程序和函數中執行的標準動作會從複製來源伺服器複製到副本。在 第 27.8 節,「預存程式二進位記錄」 中詳細描述了一些限制。

A.4.23.

在複製來源伺服器上建立的預存程序和函數是否會複製到副本?

可以,透過在複製來源伺服器上的正常 DDL 語法執行的預存程序和函數的建立會複製到副本,以便這兩個伺服器上都存在這些物件。預存程序和函數的 ALTERDROP 語法也會被複製。

A.4.24.

在預存程序和函數內部發生的動作是如何複製的?

MySQL 會記錄預存程序中發生的每個 DML 事件,並將這些個別動作複製到副本。執行預存程序的實際呼叫不會被複製。

會變更資料的預存函數會記錄為函數調用,而不是每個函數內部發生的 DML 事件。

A.4.25.

將預存程序和函數與複製功能一起使用是否有特殊的安全性要求?

有。由於副本具有執行從來源二進位記錄讀取的任何語法的權限,因此在使用預存函數進行複製時,存在特殊的安全性限制。如果複製或一般二進位記錄 (用於時間點還原) 處於活動狀態,則 MySQL DBA 有兩個安全性選項可以選擇

  1. 任何希望建立預存函數的使用者都必須被授予 SUPER 權限。

  2. 或者,DBA 可以將 log_bin_trust_function_creators 系統變數設定為 1,這會使任何具有標準 CREATE ROUTINE 權限的人都可以建立預存函數。

A.4.26.

複製預存程序和函數動作存在哪些限制?

嵌入在預存程序中的非決定性 (隨機) 或基於時間的動作可能無法正確複製。從本質上講,隨機產生的結果是不可預測的,並且無法精確重現;因此,複製到副本的隨機動作不會反映在來源上執行的動作。將預存函數宣告為 DETERMINISTIC 或將 log_bin_trust_function_creators 系統變數設定為 0 可防止調用產生隨機值的隨機操作。

此外,基於時間的動作無法在副本上重現,因為預存程序中此類動作的時序無法通過用於複製的二進位記錄重現。它僅記錄 DML 事件,不考慮時間限制。

最後,對於大型 DML 動作 (例如批量插入) 期間發生錯誤的非交易表格,可能會發生複製問題,因為來源可能會因為 DML 活動而部分更新,但由於發生錯誤,不會對副本進行更新。一種解決方法是使用 IGNORE 關鍵字執行函數的 DML 動作,以便忽略來源上導致錯誤的更新,並將未導致錯誤的更新複製到副本。

A.4.27.

上述限制是否會影響 MySQL 執行時間點還原的能力?

影響複製的相同限制也會影響時間點還原。

A.4.28.

正在做什麼來修正上述限制?

您可以選擇基於語法的複製或基於列的複製。原始複製實作是基於語法二進位記錄。基於列的二進位記錄解決了前面提到的限制。

也可以使用混合複製 (透過使用 --binlog-format=mixed 啟動伺服器)。這種混合形式的複製 知道是否可以安全地使用語法層級複製,或者是否需要列層級複製。

有關其他資訊,請參閱 第 19.2.1 節,「複製格式」