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
これらのステートメントはストアドルーチンを生成します。デフォルトでは、ルーチンはデフォルトデータベースに関連付けられます。あるデータベース中にルーチンを明確に関連させるには、生成時その名称を
db_name.sp_name
と特定してください。
CREATE FUNCTION
ステートメントはまた、UDF (ユーザー定義関数)
をサポートするために MySQL
でも使用されます。詳しくはAdding New Functions to MySQLを参照してください。UDF
は記憶された外部機能であると見なすことができます。ただし、ストアドファンクションは自身の名前空間を
UDF
と共有していることに注意してください。サーバーの異なる種類の機能に対するリファレンスの解釈を説明した規則は、項5.2.4. 「関数名の構文解析と解決」
を参照してください。
ストアドプロシージャーを呼び出すには、CALL
ステートメントを使用します (項8.2.1. 「CALL
構文」
を参照)。ストアドファンクションを呼び出すには、式でその関数を参照します。その関数は、式の評価中に値を返します。
CREATE PROCEDURE
または CREATE
FUNCTION
ステートメントを実行するには、CREATE
ROUTINE
権限を持っている必要があります。デフォルトでは、MySQL
は、ルーチン作成者に
ALTER ROUTINE
および EXECUTE
権限を自動的に与えます。
この動作は、automatic_sp_privileges
システム変数を無効にすることによって変更できます。詳しくはStored Routines and MySQL Privilegesを参照してください。Binary Logging of Stored Programs
で説明されているように、バイナリログが有効になっている場合は、CREATE
FUNCTION
ステートメントに
SUPER
権限も必要になる可能性があります。
あとで説明するように、DEFINER
および SQL SECURITY
節は、ルーチンの実行時にアクセス権限を確認するときに使用されるセキュリティーコンテキストを指定します。
ルーチン名が組み込みの SQL 関数の名前と同じである場合は、ルーチンを定義するとき、またはあとで呼び出すときに名前とそれに続く括弧の間にスペースを使用しないかぎり、構文エラーが発生します。このため、ユーザー独自のストアドルーチンに既存の SQL 関数の名前を使用することは避けてください。
IGNORE_SPACE
SQL
モードは、ストアドルーチンではなく、組み込み関数に適用されます。IGNORE_SPACE
が有効になっているかどうかには関係なく、ストアドルーチン名のあとにスペースを使用することは常に許容されます。
かっこの中に含めたパラメータリストは常に存在していなければいけません。パラメータがない場合、空欄のパラメータリスト
()
を使用すべきです。パラメータ名の大文字と小文字は区別されません。
デフォルトで各パラメータは
IN
パラメータです。上記とは別にパラメータの属性を特定する場合、OUT
または INOUT
キーワードをパラメータ名の前で使用してください。
IN
、OUT
、または
INOUT
としてのパラメータの指定は、PROCEDURE
に対してのみ有効です。(FUNCTION
パラメータは、常に
IN
パラメータと見なされます。)
IN
パラメータはプロシージャーにある値を渡します。プロシージャーはその値を修正しなければならない場合もありますが、プロシージャーが返されても、発信側にはその改良を閲覧することができません。OUT
パラメータは手順からある値を発信側に返します。プロシージャー内の初期値は
NULL
で、発信側にプロシージャーが返されるとき、その値を閲覧することができます。発信側は
INOUT
パラメータを初期化することができ、プロシージャーはそれを改良することができる上、プロシージャーによる変更はプロシージャーが返されたとき発信側で閲覧することができます。
プロシージャーを呼び出す
CALL
ステートメントでは、OUT
または INOUT
パラメータごとにユーザー定義変数を渡して、プロシージャーが終了したときにその値を取得できるようにします。保存されたほかのプロシージャーの中からプロシージャーまたはファンクションを呼び出す場合、あなたはルーチンパラメータまたはローカルルーチン変数を、IN
パラメータまたは
INOUT
パラメータとして渡すことができます。
次の例は、OUT
パラメータを使用する単純なストアドプロシージャーを示しています。
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)
この例は、プロシージャーを定義しながら、mysql
クライアント delimiter
コマンドを使用して、ステートメント区切り文字を;
から//
に変更するのに使用します。これによって、プロシージャー本体の中で使用された;
区切り文字が、mysql
自身によって解釈されないで、サーバーに転送されることが許容されます。Defining Stored Programs
を参照してください。
FUNCTION
だけに対して、遵守する義務のある
RETURNS
節を特定することができます。これは関数の戻り値の型を示すものであり、関数の本体に
RETURN
ステートメントが含まれている必要があります。保存されたプロシージャーとファンクションの
value
RETURN
ステートメントが型の異なる値を返した場合、その値は正しい値に強制的に修正されます。たとえば、ファンクションがその
RETURN
節の中に ENUM
値または SET
値を特定しますが、RETURN
ステートメントが整数を返す場合、ファンクションから返された値は、SET
メンバーのセットに対応する
ENUM
メンバーに対する文字列となります。
次の関数例はパラメータを取得し、SQL
関数を使用して操作を実行したあと、結果を返します。この場合、ファンクションの定義に内部;
ステートメント区切り文字は含まれていないので、区切り文字
を使う必要はありません。
mysql>CREATE FUNCTION hello (s CHAR(20))
mysql>RETURNS CHAR(50) DETERMINISTIC
->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)
パラメータの型と関数の戻り値の型には、COLLATE
属性は使用できませんが、それ以外の任意の有効なデータ型を使用するように宣言できます。
routine_body
は有効な SQL
プロシージャーステートメントから成り立っています。これを
SELECT
または
INSERT
のような簡単なステートメントまたは
BEGIN
や
END
を使って書かれた複合ステートメントにすることができます。複合ステートメントには、宣言、ループ並びにその他の制御構造ステートメントを含むことができます。これらのステートメントの構文は、項8.8. 「MySQL 複合ステートメント構文」
で説明されています。
MySQL はルーチンに
CREATE
および
DROP
のような DDL
ステートメントを含めることを許します。MySQL
はストアドプロシージャー
(ストアドファンクションではない) に
COMMIT
のような SQL
トランザクションステートメントを含めることも許容します。ストアドファンクションには、明示的または暗黙的なコミットまたはロールバックを実行するステートメントを含めることはできません。これらのステートメントに対するサポートは
SQL
の基準によって要求されません。当該基準はこれについて、各
DBMS
ベンダーはこれらを許すか否かを決定することができると述べています。
結果セットを返すステートメントは、ストアドプロシージャー内で使用できますが、ストアドファンクション内では使用できません。この禁止には、INTO
節を含まない
var_list
SELECT
ステートメントや、SHOW
、EXPLAIN
、CHECK
TABLE
などのほかのステートメントも含まれます。関数の定義時に、結果セットを返すことが判断できるステートメントの場合は、Not
allowed to return a result set from a function
エラーが発生します
(ER_SP_NO_RETSET
)。稼働中にだけ、結果セットを返すことを決めることが出来るステートメントに対して、PROCEDURE
%s can't return a result set in the given context
エラーが発生します
(ER_SP_BADSELECT
)。
ストアドルーチン内で
USE
ステートメントを使用することは禁止されています。ルーチンが呼び出されたときに、暗黙の
USE
が実行されます
(その後、ルーチンが終了したときに元に戻ります)。これにより、ルーチンが実行されている間、そのルーチンに特定のデフォルトデータベースが与えられます。ルーチンのデフォルトデータベース以外のデータベース内のオブジェクトへの参照は、適切なデータベース名で修飾する必要があります。
db_name
ストアドルーチン内で許可されていないステートメントの詳細については、Restrictions on Stored Routines, Triggers, and Events を参照してください。
MySQL
とのインタフェースを持つ言語で書かれたプログラムの中からストアドプロシージャーを起動する方法ついては、項8.2.1. 「CALL
構文」を参照してください。
MySQL は、ルーチンが作成されるときに有効な
sql_mode
システム変数設定を格納し、ルーチンを呼び出すときに有効なサーバー
SQL
モードには関係なく、常にこの設定を適用してルーチンを実行します。
呼び出し元の SQL モードからルーチンの SQL モードへの切り替えは、引数を評価し、結果の値をルーチンパラメータに割り当てたあとで実行されます。ルーチンを厳密な SQL モードで定義しても、非厳密モードでそのルーチンを呼び出した場合、ルーチンパラメータへの引数の割り当ては厳密モードで実行されません。ルーチンに渡された式を厳密な SQL モードで割り当てる必要がある場合は、厳密モードを有効にしてルーチンを呼び出すようにしてください。
プロシージャーあるいはファンクションは、それが同じインプットパラメータに対して常に同じ結果をもたらす場合、「決定論的」であるとみなされるが、同じ結果をもたらさない場合には、「非決定論的」であるとみなされます。ルーチンの定義に
DETERMINISTIC
も
NOT DETERMINISTIC
も附与しない場合、初期設定は
NOT DETERMINISTIC
となります。
NOW()
関数
(または、その同義語) または
RAND()
を含むルーチンは決定的ではありませんが、依然としてレプリケーションに対して安全である可能性があります。NOW()
の場合、バイナリログはタイムスタンプを含み、正しく複製されます。また
RAND()
も、ルーチンの実行中に 1
回だけ呼び出されるかぎり、正しく複製されます。
(ルーチン実行のタイムスタンプと乱数種を、マスタとスレーブが同じインプットとみなすことができます)。
MySQL 5.1.21
より前のバージョンでは、DETERMINISTIC
特性は受け入れられますが、オプティマイザで使用されません。ただし、バイナリログが有効になっている場合、この特性は
MySQL
がどのルーチン定義を受け入れるかに常に影響を与えます。Binary Logging of Stored Programs
を参照してください。
幾つかの特徴は、ルーチンによるデータ使用の性質に関する情報を提供します。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
機能を設定する方法によって、規定者か利用者のいずれかになります。
COMMENT
特性は MySQL
の拡張機能であり、ストアドルーチンを説明するために使用できます。この情報は
SHOW CREATE
PROCEDURE
ステートメントと
SHOW CREATE
FUNCTION
ステートメントによって表示されます。
オプションの DEFINER
節は SQL SECURITY DEFINER
特徴を有するルーチンに対して、実行中にアクセス権限を確認する時使用すべき
MySQL
アカウントを特定します。DEFINER
節は MySQL 5.1.8.で追加されました。
DEFINER
節に対して
user
値を指定する場合は、'
の形式 (user_name
'@'host_name
'GRANT
ステートメントで使用されるのと同じ形式) の
MySQL
アカウントである必要があります。user_name
の値と host_name
の値が両方共要求されます。定義者はまた、CURRENT_USER
または
CURRENT_USER()
として指定することもできます。DEFINER
の初期値は CREATE
PROCEDURE
または
CREATE FUNCTION
またはステートメントを実行するユーザーです。(これは
DEFINER = CURRENT_USER
と同じです)。
DEFINER
節を指定する場合は、これらの規則によって正当な
DEFINER
ユーザー値が決定されます。
SUPER
権限を持っていない場合、文字によるか、CURRENT_USER
を使って規定されている
user
値だけが有効なユーザーアカウントとなります。定義子をほかのアカウントに設定することはできません。
SUPER
権限を持っている場合、構文的に有効なアカウントネームを規定することができます。そのアカウントが実在しない場合、警告が生成されます。
存在しない DEFINER
値を使用してルーチンを作成できますが、そのルーチンが定義者の権限で実行されたにもかかわらず、実行時にその定義者が存在しない場合はエラーが発生します。
SQL SECURITY DEFINER
特性を使用して定義されたストアドルーチン内で、CURRENT_USER
は、そのルーチンの
DEFINER
値を返します。ストアドルーチン内のユーザー監査については、Auditing MySQL Account Activity
を参照してください。
mysql.user
テーブルにリストされている MySQL
アカウントの数を表示する次のプロシージャーを考えてみます。
CREATE DEFINER = 'admin'@'localhost' PROCEDURE account_count() BEGIN SELECT 'Number of accounts:', COUNT(*) FROM mysql.user; END;
どのユーザーが定義した場合でも、このプロシージャーには
'admin'@'localhost'
の
DEFINER
アカウントが割り当てられます。どのユーザーから呼び出された場合でも、このプロシージャーは、そのアカウントの権限で実行されます
(デフォルトのセキュリティー特性が
DEFINER
であるため)。'admin'@'localhost'
がこのプロシージャーに対する
EXECUTE
権限と、mysql.user
テーブルに対する
SELECT
権限を持っているかどうかに応じて、このプロシージャーは成功または失敗します。
ここで、このプロシージャーが
SQL SECURITY INVOKER
特性を使用して定義されているとします。
CREATE DEFINER = 'admin'@'localhost' PROCEDURE account_count() SQL SECURITY INVOKER BEGIN SELECT 'Number of accounts:', COUNT(*) FROM mysql.user; END;
このプロシージャーは、依然として
'admin'@'localhost'
の
DEFINER
を持っていますが、この場合は呼び出し元ユーザーの権限で実行されます。そのため、このプロシージャーは、呼び出し元が必要な権限を持っているかどうかに応じて成功または失敗します。
サーバーは、ルーチンパラメータ、DECLARE
を使用して作成されたローカルルーチン変数、または関数の戻り値のデータ型を次のように処理します。
割り当てたデータにミスマッチおよびオーバーフローがないか確認します。変換やオーバーフローの問題によって警告が発生するか、または厳密な SQL モードではエラーが発生します。
スカラー値のみを割り当てることができます。たとえば、SET
x = (SELECT 1, 2)
のようなステートメントは無効です。
文字データ型で、宣言内に
CHARACTER SET
属性が存在する場合は、指定されたキャラクタセットとそのデフォルトの照合が使用されます。このような属性が存在しない場合は、ルーチンの作成時に有効なデータベースのキャラクタセットとそのデフォルトの照合が使用されます。
(データベースのキャラクタセットは
character_set_database
システム変数の値で指定されます。)
COLLATE
属性はサポートされていません。(このコンテキスト
BINARY
はキャラクタセットのバイナリー照合順序を規定するので、これには
BINARY
の使用が含まれます)。