これらの制約は、第25章「ストアドオブジェクト」で説明している機能に適用されます。
ここに記載されている制約の中には、すべてのストアドルーチン、つまりストアドプロシージャーとストアドファンクションの両方に適用されるものがあります。 また、ストアドプロシージャーには適用されず、ストアドファンクションに固有の制約もいくつか存在します。
ストアドファンクションの制約は、トリガーにも適用されます。 トリガーに固有の制約もいくつかあります。
ストアドプロシージャーの制約は、イベントスケジューラのイベント定義の DO
句にも適用されます。 イベントに固有の制約もいくつかあります。
ストアドルーチンには自由に SQL ステートメントを含めることはできません。 次のステートメントは許可されていません。
LOCK TABLES
およびUNLOCK TABLES
のロックステートメント。ALTER VIEW
LOAD DATA
。SQL 準備済みステートメント (
PREPARE
、EXECUTE
、DEALLOCATE PREPARE
) は、ストアドプロシージャーで使用できますが、ストアドファンクションやトリガーでは使用できません。 そのため、ストアドファンクションとトリガーは動的 SQL (この場合はステートメントを文字列として構築してから実行します) を使用できません。通常、SQL 準備済みステートメントで許可されていないステートメントは、ストアドプログラムでも許可されません。 準備済みステートメントとしてサポートされているステートメントのリストについては、セクション13.5「プリペアドステートメント」を参照してください。 例外は
SIGNAL
、RESIGNAL
、およびGET DIAGNOSTICS
であり、これらは準備済みステートメントとして許可されていませんが、ストアドプログラムで許可されます。ローカル変数はストアドプログラムの実行中にのみスコープ内にあるので、これらの参照は、ストアドプログラム内で作成された準備済みステートメントでは許可されていません。 準備済みステートメントのスコープは現在のセッションであり、ストアドプログラムではないので、ステートメントはプログラムの終了後に実行でき、この時点で変数はスコープ内に存在しなくなります。 たとえば、
SELECT ... INTO
は準備済みステートメントとして使用できません。 この制約は、ストアドプロシージャーおよびストアドファンクションのパラメータにも適用されます。 セクション13.5.1「PREPARE ステートメント」を参照してください。local_var
すべてのストアドプログラム (ストアドプロシージャーとストアドファンクション、トリガー、およびイベント) 内で、パーサーは、
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.10.1「SELECT ... INTO ステートメント」およびセクション13.6.6「カーソル」を参照してください。FLUSH
ステートメント。ストアドファンクションは再帰的に使用できません。
ストアドファンクションまたはトリガーは、そのストアドファンクションまたはトリガーを呼び出したステートメントによって (読み取りまたは書き込みに) すでに使用されているテーブルを変更できません。
ストアドファンクションで、一時テーブルを異なるエイリアスで複数回参照する場合、ストアドファンクション内の別々のステートメントで参照を行う場合でも、
「表を再オープンできません: '
というエラーが発生します。tbl_name
'」
ストアドファンクションを呼び出す
HANDLER ... READ
ステートメントは、レプリケーションエラーを引き起こす可能性があり、許可されません。
トリガーの場合、さらに次の制約が適用されます。
トリガーは外部キーアクションでアクティブ化されません。
行ベースのレプリケーションを使用している場合、レプリカのトリガーは、ソースで発生したステートメントによってアクティブ化されません。 レプリカのトリガーは、ステートメントベースレプリケーションを使用している場合にアクティブになります。 詳細は、セクション17.5.1.36「レプリケーションとトリガー」を参照してください。
RETURN
ステートメントはトリガーでは許可されていません。トリガーは値を返すことができません。 すぐにトリガーを終了するには、LEAVE
ステートメントを使用します。トリガーは、
mysql
データベース内のテーブルでは許可されていません。INFORMATION_SCHEMA
またはperformance_schema
テーブルでも許可されていません。 これらのテーブルは実際にはビューであり、トリガーはビューでは許可されません。トリガーキャッシュは、ベースとなるオブジェクトのメタデータが変更された場合は検出しません。 トリガーがテーブルを使用し、トリガーがキャッシュにロードされたあとにそのテーブルに変更があった場合、トリガーは古いメタデータを使用して動作します。
ルーチンパラメータ、ローカル変数、およびテーブルカラムに同じ識別子が使用される場合があります。 また、同じローカル変数名を、ネスト化されたブロックで使用することもできます。 例:
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;
このような場合、識別子はあいまいになり、次の優先順位ルールが適用されます。
ローカル変数では、ルーチンパラメータやテーブルカラムが優先されます。
ルーチンパラメータでは、テーブルカラムが優先されます。
内部ブロック内のローカル変数では、外部ブロック内のローカル変数が優先されます。
変数でテーブルカラムが優先される動作は、非標準です。
ストアドルーチンを使用すると、レプリケーションの問題が生じることがあります。 この問題については、セクション25.7「ストアドプログラムバイナリロギング」で詳しく述べられています。
--replicate-wild-do-table=
オプションはテーブル、ビュー、およびトリガーに適用されます。 ストアドプロシージャーと関数、またはイベントには適用されません。 後者のオブジェクトで作用するステートメントをフィルタするには、1 つまたは複数の db_name.tbl_name
--replicate-*-db
オプションを使用します。
MySQL ストアドルーチン構文は SQL:2003 標準に基づきます。 この標準の次の項目は現在サポートされていません。
UNDO
ハンドラFOR
ループ
セッション間のやり取りの問題を防止するために、クライアントのステートメント発行時、サーバーではステートメントの実行に利用できるルーチンとトリガーのスナップショットが使用されます。 つまり、サーバーは、ステートメントの実行中に使用される可能性のあるプロシージャー、関数、およびトリガーのリストを算出してロードし、ステートメントの実行に進みます。 ステートメントの実行時は、ほかのセッションが実行するルーチンへの変更は認識されません。
並列性を最大にするために、ストアドファンクションでは、その副作用を最小限に抑える必要があります。特に、ストアドファンクション内のテーブルを更新することにより、そのテーブルでの並列操作が減少することがあります。 ストアドファンクションは、実行前にテーブルロックを取得して、ステートメントが実行する順序とログに表示されるときの順序の不一致によるバイナリログの不整合を回避します。 ステートメントベースのバイナリロギングが使用される場合、関数内で実行されるステートメントではなく、関数を呼び出すステートメントが記録されます。 その結果、ベースとなる同じテーブルを更新するストアドファンクションは、並列で実行しません。 対照的に、ストアドプロシージャーはテーブルレベルのロックを取得しません。 ストアドプロシージャー内で実行されたすべてのステートメントは、ステートメントベースのバイナリロギングの場合でも、バイナリログに書き込まれます。 セクション25.7「ストアドプログラムバイナリロギング」を参照してください。
次の制限は、イベントスケジューラに固有のものです。
イベント名は大文字と小文字を区別せずに処理されます。 たとえば、
anEvent
とAnEvent
という名前の 2 つのイベントを同じデータベース内に含めることはできません。イベント名が変数によって指定されている場合、ストアドプログラム内からイベントを作成、変更、または削除することはできません。 イベントは、ストアドルーチンやトリガーを作成、変更、削除することもできません。
LOCK TABLES
ステートメントの有効時は、イベントでの DDL ステートメントは禁止されています。YEAR
、QUARTER
、MONTH
、およびYEAR_MONTH
の間隔を使用したイベントのタイミングは、月で解決されます。ほかの間隔を使用したタイミングは秒で解決されます。 同時に行われるようにスケジュール設定されたイベントは、指定の順序で実行できません。 さらに、丸め、スレッドアプリケーションの特性、およびイベントを作成しその実行を信号で伝えるためにゼロ以外の時間長が必要になるため、イベントが 1、2 秒ほど遅れる場合があります。 ただし、INFORMATION_SCHEMA.EVENTS
テーブルの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 を参照してください。)
ストアドプロシージャ、ストアドファンクション、トリガーおよびスケジュール済イベントはすべて、NDB
ストレージエンジンを使用するテーブルでサポートされますが、これらはクラスタ SQL ノードとして機能する MySQL Servers 間で自動的に伝播されないことに注意する必要があります。 これは、ストアドルーチンおよびトリガー定義が、クラスタノード間でコピーされない InnoDB
テーブルを使用して mysql
システムデータベース内のテーブルに格納されるためです。
MySQL Cluster テーブルと対話するストアドルーチンまたはトリガーは、ストアドルーチンまたはトリガーを使用するクラスタに参加する各 MySQL Server で適切な CREATE PROCEDURE
、CREATE FUNCTION
、または CREATE TRIGGER
ステートメントを実行して再作成する必要があります。 同様に、既存のストアドルーチンまたはトリガーに対する変更は、クラスタにアクセスする各 MySQL Server で適切な ALTER
ステートメントまたは DROP
ステートメントを使用して、すべてのクラスタ SQL ノードで明示的に実行する必要があります。
NDB
ストレージエンジンを使用するように mysql
データベーステーブルを変換して、ここで説明した問題を回避しないでください。 「mysql
データベースでのシステムテーブルの変更はサポートされていません」では、望ましくない結果が生成される可能性があります。