これらの制約は、第20章「ストアドプログラムおよびビュー」で説明している機能に適用されます。
ここに記載されている制約の中には、すべてのストアドルーチン、つまりストアドプロシージャーとストアドファンクションの両方に適用されるものがあります。また、ストアドプロシージャーには適用されず、ストアドファンクションに固有の制約もいくつか存在します。
ストアドファンクションの制約は、トリガーにも適用されます。トリガーに固有の制約もいくつかあります。
ストアドプロシージャーの制約は、イベントスケジューラのイベント定義の DO
句にも適用されます。イベントに固有の制約もいくつかあります。
ストアドルーチンでは許可されていない SQL ステートメント
ストアドルーチンには自由に SQL ステートメントを含めることはできません。次のステートメントは許可されていません。
LOCK TABLES
およびUNLOCK TABLES
のロックステートメント。ALTER VIEW
。LOAD DATA
およびLOAD TABLE
。SQL 準備済みステートメント (
PREPARE
、EXECUTE
、DEALLOCATE PREPARE
) は、ストアドプロシージャーで使用できますが、ストアドファンクションやトリガーでは使用できません。そのため、ストアドファンクションとトリガーは動的 SQL (この場合はステートメントを文字列として構築してから実行します) を使用できません。通常、SQL 準備済みステートメントで許可されていないステートメントは、ストアドプログラムでも許可されません。準備済みステートメントとしてサポートされているステートメントのリストについては、セクション13.5「準備済みステートメントのための SQL 構文」を参照してください。例外は
SIGNAL
、RESIGNAL
、およびGET DIAGNOSTICS
であり、これらは準備済みステートメントとして許可されていませんが、ストアドプログラムで許可されます。ローカル変数はストアドプログラムの実行中にのみスコープ内にあるので、これらの参照は、ストアドプログラム内で作成された準備済みステートメントでは許可されていません。準備済みステートメントのスコープは現在のセッションであり、ストアドプログラムではないので、ステートメントはプログラムの終了後に実行でき、この時点で変数はスコープ内に存在しなくなります。たとえば、
SELECT ... INTO
は準備済みステートメントとして使用できません。この制約は、ストアドプロシージャーおよびストアドファンクションのパラメータにも適用されます。セクション13.5.1「PREPARE 構文」を参照してください。local_var
挿入は遅延されません。
INSERT DELAYED
構文は受け入れられますが、ステートメントは通常のINSERT
として扱われます。すべてのストアドプログラム (ストアドプロシージャーとストアドファンクション、トリガー、およびイベント) 内で、パーサーは、
BEGIN [WORK]
をBEGIN ... END
ブロックの開始として扱います。このコンテキストでトランザクションを開始するには、代わりにSTART TRANSACTION
を使用します。
ストアドファンクションの制約
次の追加ステートメントまたは操作は、ストアドファンクション内で許可されていません。これらはストアドプロシージャーで許可されていますが、ストアドファンクションまたはトリガー内から呼び出されるストアドプロシージャーを除きます。たとえば、ストアドプロシージャーで FLUSH
を使用する場合、ストアドファンクションまたはトリガーからそのストアドプロシージャーを呼び出すことはできません。
明示的または暗黙的なコミットまたはロールバックを実行するステートメント。これらのステートメントのサポートは、SQL 標準では必要ありません。SQL 標準では、各 DBMS ベンダーがこれらのステートメントを許可するかどうかを決められると定めています。
結果セットを返すステートメント。これには、
INTO
句を含まないvar_list
SELECT
ステートメントや、SHOW
、EXPLAIN
、およびCHECK TABLE
などのほかのステートメントも含まれます。関数は、SELECT ... INTO
を使用するか、カーソルとvar_list
FETCH
ステートメントを使用すると、結果セットを処理できます。セクション13.2.9.1「SELECT ... INTO 構文」およびセクション13.6.6「カーソル」を参照してください。FLUSH
ステートメント。ストアドファンクションは再帰的に使用できません。
ストアドファンクションまたはトリガーは、そのストアドファンクションまたはトリガーを呼び出したステートメントによって (読み取りまたは書き込みに) すでに使用されているテーブルを変更できません。
ストアドファンクションで、一時テーブルを異なるエイリアスで複数回参照する場合、ストアドファンクション内の別々のステートメントで参照を行う場合でも、
「表を再オープンできません: '
というエラーが発生します。tbl_name
'」
ストアドファンクションを呼び出す
HANDLER ... READ
ステートメントは、レプリケーションエラーを引き起こす可能性があり、許可されません。
トリガーの制約
トリガーの場合、さらに次の制約が適用されます。
トリガーは外部キーアクションでアクティブ化されません。
行ベースのレプリケーションを使用する場合、スレーブのトリガーは、マスターから発行されたステートメントでアクティブ化されません。スレーブのトリガーは、ステートメントベースのレプリケーションを使用するときにアクティブ化されます。詳細は、セクション17.4.1.32「レプリケーションとトリガー」を参照してください。
RETURN
ステートメントはトリガーでは許可されていません。トリガーは値を返すことができません。すぐにトリガーを終了するには、LEAVE
ステートメントを使用します。トリガーは、
mysql
データベース内のテーブルでは許可されていません。トリガーキャッシュは、ベースとなるオブジェクトのメタデータが変更された場合は検出しません。トリガーがテーブルを使用し、トリガーがキャッシュにロードされたあとにそのテーブルに変更があった場合、トリガーは古いメタデータを使用して動作します。
ストアドルーチン内の名前競合
ルーチンパラメータ、ローカル変数、およびテーブルカラムに同じ識別子が使用される場合があります。また、同じローカル変数名を、ネスト化されたブロックで使用することもできます。例:
CREATE PROCEDURE p (i INT)
BEGIN
DECLARE i INT DEFAULT 0;
SELECT i FROM t;
BEGIN
DECLARE i INT DEFAULT 1;
SELECT i FROM t;
END;
END;
このような場合、識別子はあいまいになり、次の優先順位ルールが適用されます。
ローカル変数では、ルーチンパラメータやテーブルカラムが優先されます。
ルーチンパラメータでは、テーブルカラムが優先されます。
内部ブロック内のローカル変数では、外部ブロック内のローカル変数が優先されます。
変数でテーブルカラムが優先される動作は、非標準です。
レプリケーションに関する考慮事項
ストアドルーチンを使用すると、レプリケーションの問題が生じることがあります。この問題については、セクション20.7「ストアドプログラムのバイナリロギング」で詳しく述べられています。
--replicate-wild-do-table=
オプションはテーブル、ビュー、およびトリガーに適用されます。ストアドプロシージャーと関数、またはイベントには適用されません。後者のオブジェクトで作用するステートメントをフィルタするには、1 つまたは複数の db_name.tbl_name
--replicate-*-db
オプションを使用します。
デバッグに関する考慮事項
ストアドルーチンのデバッグ機能は存在しません。
SQL:2003 標準のサポート外の構文
MySQL ストアドルーチン構文は SQL:2003 標準に基づきます。この標準の次の項目は現在サポートされていません。
UNDO
ハンドラFOR
ループ
並列性に関する考慮事項
セッション間のやり取りの問題を防止するために、クライアントのステートメント発行時、サーバーではステートメントの実行に利用できるルーチンとトリガーのスナップショットが使用されます。つまり、サーバーは、ステートメントの実行中に使用される可能性のあるプロシージャー、関数、およびトリガーのリストを算出してロードし、ステートメントの実行に進みます。ステートメントの実行時は、ほかのセッションが実行するルーチンへの変更は認識されません。
並列性を最大にするために、ストアドファンクションでは、その副作用を最小限に抑える必要があります。特に、ストアドファンクション内のテーブルを更新することにより、そのテーブルでの並列操作が減少することがあります。ストアドファンクションは、実行前にテーブルロックを取得して、ステートメントが実行する順序とログに表示されるときの順序の不一致によるバイナリログの不整合を回避します。ステートメントベースのバイナリロギングが使用される場合、関数内で実行されるステートメントではなく、関数を呼び出すステートメントが記録されます。その結果、ベースとなる同じテーブルを更新するストアドファンクションは、並列で実行しません。対照的に、ストアドプロシージャーはテーブルレベルのロックを取得しません。ストアドプロシージャー内で実行されたすべてのステートメントは、ステートメントベースのバイナリロギングの場合でも、バイナリログに書き込まれます。セクション20.7「ストアドプログラムのバイナリロギング」を参照してください。
イベントスケジューラの制約
次の制限は、イベントスケジューラに固有のものです。
イベント名は大文字と小文字を区別せずに処理されます。たとえば、
anEvent
とAnEvent
という名前の 2 つのイベントを同じデータベース内に含めることはできません。イベントは、ストアドルーチン、トリガー、または別のイベントによって、作成、変更、削除できません。イベントは、ストアドルーチンやトリガーを作成、変更、削除することもできません。(Bug #16409、Bug #18896)
LOCK TABLES
ステートメントの有効時は、イベントでの DDL ステートメントは禁止されています。YEAR
、QUARTER
、MONTH
、およびYEAR_MONTH
の間隔を使用したイベントのタイミングは、月で解決されます。ほかの間隔を使用したタイミングは秒で解決されます。同時に行われるようにスケジュール設定されたイベントは、指定の順序で実行できません。さらに、丸め、スレッドアプリケーションの特性、およびイベントを作成しその実行を信号で伝えるためにゼロ以外の時間長が必要になるため、イベントが 1、2 秒ほど遅れる場合があります。ただし、INFORMATION_SCHEMA.EVENTS
テーブルのLAST_EXECUTED
カラム、またはmysql.event
テーブルのlast_executed
カラムに示された時間は、常に実際のイベント実行時間の 1 秒以内の精度になります。(Bug #16522 も参照してください。)イベントの本体に含まれるステートメントはそれぞれ新しい接続で実行されるため、これらのステートメントは特定のユーザーセッションで、
SHOW STATUS
によって表示されるCom_select
やCom_insert
などのサーバーのステートメント数に影響しません。ただし、このような数はグローバルスコープで更新されます。(Bug #16422)イベントは、Unix エポックの最後の時間以降をサポートしません。この時間は 2038 年の年頭あたりになります。このような日付はイベントスケジューラで特に許可されません。(Bug #16396)
CREATE EVENT
およびALTER EVENT
ステートメントのON SCHEDULE
句でのストアドファンクション、ユーザー定義関数、およびテーブルの参照はサポートされていません。このような種類の参照は許可されていません。(詳細は Bug #22830 を参照してください。)