CREATE [DEFINER = {user
| CURRENT_USER }] PROCEDUREsp_name
([proc_parameter
[,...]]) [characteristic
...]routine_body
CREATE [DEFINER = {user
| CURRENT_USER }] FUNCTIONsp_name
([func_parameter
[,...]]) RETURNStype
[characteristic
...]routine_body
proc_parameter
: [ IN | OUT | INOUT ]param_name
type
func_parameter
:param_name
type
type
:Any valid MySQL data type
characteristic
: LANGUAGE SQL | [NOT] DETERMINISTIC | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA } | SQL SECURITY { DEFINER | INVOKER } | COMMENT 'string
'routine_body
:Valid SQL procedure statement
これらのステートメントはストアドルーチンを生成します。これらを使用するにはCREATE
ROUTINE
権限を持っていることが必要です。バイナリログが有効化されている場合、CREATE
FUNCTION
ステートメントにもSUPER
権限が項17.4. 「ストアドルーチンとトリガのバイナリログ」で述べた通り、要求されます。MySQLはALTER
ROUTINE
権限とEXECUTE
権限をルーチン生成者に自動的に供与します。
デフォルトで、そのルーチンは初期設定データベースに関連されます。あるデータベース中にルーチンを明確に関連させるには、生成時その名称をdb_name.sp_name
と特定してください。
ルーチン名が組み込まれているSQL機能と同じである場合、ルーチンを定義する時、名称とその後のかっこの間にスペースを使用しなければなりません。 これを怠ると、構文エラーが発生します。これは、後にルーチンを呼び出す場合にも当てはまります。この理由によって、保存されているユーザ自身のルーチンに対してSQLの既存のファンクション名称を再使用しないようお勧めします。
IGNORE_SPACE
SQLモードは、ストアドルーチンでなく、組み込まれているファンクションに適用され、IGNORE_SPACE
が有効になっているか否かにかかわりなく、ルーチン名の後にスペースを含むことは常に許容されています。
かっこの中に含めたパラメータリストは常に存在していなければいけません。パラメータがない場合、空欄のパラメータリスト()
を使用すべきです。
各パラメータには、COLLATE
属性は使用できないことを除けば、有効なデータタイプを使用していると宣言できます。
デフォルトで各パラメータはIN
パラメータです。上記とは別にパラメータの属性を特定する場合、OUT
またはINOUT
キーワードをパラメータ名の前で使用してください。
注:パラメータにIN
、OUT
しくはINOUT
と特定することはPROCEDURE
に対してのみ有効です。(FUNCTION
パラメータは常にIN
パラメータと見なされます。
IN
パラメータはプロシージャにある値を渡します。プロシージャはその値を修正しなければならない場合もありますが、プロシージャが返されても、発信側にはその改良を閲覧することができません。OUT
パラメータは手順からある値を発信側に返します。プロシージャ内の初期値はNULL
で、発信側にプロシージャが返されるとき、その値を閲覧することができます。発信側はINOUT
パラメータを初期化することができ、プロシージャはそれを改良することができる上、プロシージャによる変更はプロシージャが返されたとき発信側で閲覧することができます。
各OUT
パラメータもしくはINOUT
パラメータは、ユーザに特定された変数を渡すことで、プロシージャが返されたときにその値を取得できます。(例については、項17.2.4. 「CALL
ステートメント構文」を参照してください。)保存された他のプロシージャの中からプロシージャまたはファンクションを呼び出す場合、あなたはルーチンパラメータまたはローカルルーチン変数を、IN
パラメータまたはINOUT
パラメータとして渡すことができます。
FUNCTION
だけに対して、遵守する義務のあるRETURNS
節を特定することができます。それは、ファンクションのリターンタイプとファンクション本体には、RETURN
ステートメントが含まれていなければならないことを示します。保存されたプロシージャとファンクションのvalue
RETURN
ステートメントがタイプの異なる値を戻した場合、その値は正しい値に強制的に修正されます。例えば、ファンクションがそのRETURN
節の中にENUM
値またはSET
値を特定しますが、RETURN
ステートメントが整数を戻す場合、ファンクションから返された値は、SET
メンバーのセットに対応するENUM
メンバーに対する文字列となります。
routine_body
は有効なSQLプロシージャステートメントから成り立っています。これをSELECT
またはINSERT
のような簡単なステートメントもしくはBEGIN
やEND
を使って書かれた複合ステートメントにすることができます。複合ステートメントの構文については、項17.2.5. 「BEGIN ... END
複合ステートメント構文」を参照してください。複合ステートメントには、宣言、ループ並びにその他の制御構造ステートメントを含むことができます。これらのステートメントに対する構文については、この章の後半部分で説明します。例えば、項17.2.6. 「DECLARE
ステートメント用構文」並びに項17.2.10. 「フローコントロール・コンストラクト」を参照してください。いくつかのステートメントはストアドルーチン内で使用することはできません(項D.1. 「ストアド ルーチンとトリガの規制」を参照してください)
ルーチンが生成されたとき、MySQLは有効化されていたsql_mode
システム変数設定を保存し、現サーバのSQL
モードに関係なく、必ずこの設定でルーチンを実行します。
CREATE
FUNCTION
ステートメントはUDF(ユーザ定義機能)をサポートするため、旧バージョンのMySQLで使用されています。項25.3. 「Adding New Functions to MySQL」を参照してください。UDFは保存されたファンクションが存在していてもサポートされ続けます。UDFは記憶された外部機能であると見なすことができます。ただし、保存されたファンクションは自身の名称スペースをUDFと共有していることに注意してください。サーバが異なった種類のファンクションに対するリファレンスを解釈する方法を述べた規則については、項8.2.4. 「構文解析と解像度のファンクション名」を参照してください。
プロシージャあるいはファンクションは、それが同じインプットパラメータに対して常に同じ結果をもたらす場合、「決定論的」であるとみなされるが、同じ結果をもたらさない場合には、「非決定論的」であるとみなされます。ルーチンの定義にDETERMINISTIC
もNOT
DETERMINISTIC
も附与しない場合、初期設定はNOT
DETERMINISTIC
となります。
NOW()
関数(またはその同義語)またはRAND()
を含むルーチンは非決定論的であるが、複製に対して耐性を保持していることがあります。NOW()
の場合、バイナリ
ログはタイムスタンプを含み、正しく複製します。RAND()
はルーチンの中で唯一回起動しただけで、正しく複製します。(ルーチン実行のタイムスタンプと乱数種を、マスタとスレーブが同じインプットとみなすことができます。)
現在、DETERMINISTIC
特性は容認されていますが、まだオプチマイザによって使用されていません。ただし、バイナリログが有効化されている場合、この特徴はMySQLがどのルーチン定義を受け入れるかに影響します。項17.4. 「ストアドルーチンとトリガのバイナリログ」
を参照してください。
幾つかの特徴は、ルーチンによるデータ使用の性質に関する情報を提供します。MySQLでは、これらの特性は助言のみです。サーバはルーチンに実行が許されるステートメントの種類を制限するために、それらを使用しません。
CONTAINS
SQL
はルーチンにはデータを読み書きするステートメントは含まれていないことを示しています。これらの特性が明確に附与されていない場合、これがデフォルトとなります。このようなステートメントの例は、SET
@x = 1
または DO
RELEASE_LOCK('abc')
です。これは、データの実行はしても読み書きを行いません。
NO
SQL
はルーチンにSQLステートメントが含まれていないことを示します。
READS SQL
DATA
は、ルーチンには(例えば、SELECT
のように)データを読み取るが、書き取らないステートメントが含まれていることを示します。
MODIFIES SQL
DATA
は、ルーチンには(例えば、INSERT
もしくはDELETE
のように)データを書き取ることができるステートメントが含まれていることを示します。
SQL
SECURITY
特徴はルーチンを生成させるユーザあるいはそれを呼び出すユーザの許可を使って、ルーチンが実行されるべきか否かを明示するために使うことができます。そのデフォルトはDEFINER
です。この特徴はSQL:2003の新機能です。その生成者や利用者は、ルーチンが属するデータベースにアクセスできる許可を取得していなければなりません。ルーチンを実行することができるEXECUTE
権限を持つ必要があります。この権限を持たなければいけないユーザは、SQL
SECURITY
機能を設定する方法によって、規定者か利用者のいずれかになります。
オプションのDEFINER
節はSQL
SECURITY
DEFINER
特徴を有するルーチンに対して、実行中にアクセス権限をチェックする時使用すべきMySQLアカウントを特定します。DEFINER
節はMySQL
5.1.8.で追加されました。
user
値を附与する場合、それを '
フォーマット(user_name
'@'
host_name
' GRANT
ステートメントに使用したと同じフォーマット)の中にあるMySQLアカウントにすべきです。user_name
の値とhost_name
の値が両方共必要です。CURRENT_USER
をCURRENT_USER()
として附与することもできます。DEFINER
の初期値はCREATE
PROCEDURE
もしくはCREATE
FUNCTION
もしくはステートメントを実行するユーザです。(これはDEFINER
= CURRENT_USER
と同じです。)
DEFINER
節を特定する場合、SUPER
権限を保持していない限り、自分の値を除くいかなるアカウントにも値をセットすることはできません。これらの規則はDEFINER
ユーザの法定値を定義します。
SUPER
権限を保持していない場合、文字によるか、CURRENT_USER
を使って規定されているuser
法定値のみがユーザのアカウントとなります。デファイナーを別のアカウントに設定することはできません。
SUPER
権限を保持している場合、構文的に規定した有効なアナウントネームを特定することができます。そのアカウントが実在しない場合、警告が生成されます。
架空のDEFINER
値を使ってルーチンを生成させることは可能ですが、ルーチンをDEFINER権限を使って実行すると、エラーが発生します。しかし定義者は実行中には存在しません。
ルーチンを起動すると、必然的に USE
が実行(ルーチンの実行が終わると自然に停止)されます。ストアドルーチン内でdb_name
USE
ステートメントを使用することは禁止されています。
サーバはルーチンパラメータのデータタイプまたはファンクションリターン値を以下の通り使用します:これらの規則はDECLARE
ステートメント(項17.2.7.1. 「DECLARE
ローカル変数」)で生成されたルーチン変数にも適用します。
割り当てたデータにミスマッチおよびオーバーフローがないかチェックします。警告の中に変換やオーバーフローの問題が、またストリクトモードにエラーがそれぞれもたらされます。
文字データタイプに対して、宣言文中にCHARACTER
SET
節がある場合、指定されたキャラクタセットとそのデフォルト照合順序が使用されます。このような節がない場合、ルーチンが生成される時有効であったデータベースキャラクタセットと照合順序が使用されます。(これらはcharacter_set_database
システム変数およびcollation_database
システム変数の値によって附与されます。)COLLATE
属性はサポートされていません。(このコンテキストBINARY
はキャラクタセットのバイナリー照合順序を規定するので、これにはBINARY
の使用が含まれます。)
パラメータや変数にはスカラー値のみ割り当てることができます。例えば、SET
x = (SELECT 1,
2)
のようなステートメントは無効です。
COMMENT
節はMySQLの拡張に含まれ、これはストアドルーチンの説明に使われます。この情報はSHOW
CREATE PROCEDURE
ステートメントとSHOW
CREATE
FUNCTION
ステートメントによって表示されます。
MySQLはルーチンにCREATE
およびDROP
のようなDDLステートメントを含めることを許します。MySQLはストアドプロシージャ
(保存されたファンクションではない)にCOMMIT
のようなSQLトランザクションステートメントを含めることも許容します。保存されたファンクションに明示、黙示、コミットもしくは反論を行うステートメントを含めることは許容されません。これらのステートメントに対するサポートはSQLの基準によって要求されません。当該基準はこれについて、各DBMSベンダーはこれらを許すか否かを決定することができると述べています。
ストアドルーチンはLOAD DATA
INFILE
を使用することができません。
結果のセットを返すステートメントを保存されたファンクション内で使うことができません。これには、カラム値を変数に取り込むためにINTO
を使わないSELECT
ステートメント、SHOW
ステートメント並びにEXPLAIN
のようなその他のステートメントが含まれています。ファンクションを規定する時、結果セットを戻すことを定義できるステートメントに対して、Not
allowed to return a result set from a
function
エラーが発生します(ER_SP_NO_RETSET_IN_FUNC
)。稼動中にだけ、結果セットを返すことを決めることが出来るステートメントに対して、PROCEDURE
%s can't return a result set in the given
context
エラーが発生します(ER_SP_BADSELECT
)。
以下は、OUT
パラメータを使用する簡単なストアドプロシージャの例を示したものです。この例は、プロシージャを定義しながら、mysqlクライアントdelimiter
コマンドを使用して、
ステートメントデリミタを;
から//
に変更するのに使用します。これによって、プロシージャ本体の中で使用された;
デリミタが、mysql自身によって解釈されないで、サーバに転送されることが許容されます。
mysql>delimiter //
mysql>CREATE PROCEDURE simpleproc (OUT param1 INT)
->BEGIN
->SELECT COUNT(*) INTO param1 FROM t;
->END;
->//
Query OK, 0 rows affected (0.00 sec) mysql>delimiter ;
mysql>CALL simpleproc(@a);
Query OK, 0 rows affected (0.00 sec) mysql>SELECT @a;
+------+ | @a | +------+ | 3 | +------+ 1 row in set (0.00 sec)
delimiter
コマンドを使用する時、MySQLに対してエスケープキャラクタとなるので、バックスラッシュ
(‘\
’)
キャラクターの使用を避けてください。
パラメータを取り込み、SQL機能を使ってオペレーションを行って結果を返すファンクションの例を次に紹介します。この場合、ファンクションの定義に内部;
ステートメントデリミタは含まれていないので、デリミタ
を使う必要はありません。
mysql>CREATE FUNCTION hello (s CHAR(20)) RETURNS CHAR(50)
->RETURN CONCAT('Hello, ',s,'!');
Query OK, 0 rows affected (0.00 sec) mysql>SELECT hello('world');
+----------------+ | hello('world') | +----------------+ | Hello, world! | +----------------+ 1 row in set (0.00 sec)
MySQLとのインターフェースを持つ言語で書かれたプログラムの中からストアドプロシージャを起動する方法ついては、項17.2.4. 「CALL
ステートメント構文」を参照してください。