私はMySQLのストアドプロシージャと関数を見ています。本当の違いは何ですか?
これらは似ているように見えますが、機能にはさらに制限があります。
私は間違っている可能性が高いですが、ストアドプロシージャはすべてを実行でき、ストアドファンクションはもっと実行できるようです。なぜ/いつプロシージャと関数を使用するのですか?
ストアドプロシージャと通常のSQLを混在させることはできませんが、ストアドファンクションを使用することはできます。
例えばSELECT get_foo(myColumn) FROM mytable
は、get_foo()
がプロシージャの場合は無効ですが、get_foo()
が関数の場合は実行できます。代償として、関数には手続きよりも多くの制限があります。
プロシージャと関数の最も一般的な違いは、それらが異なる方法で、異なる目的で呼び出されることです:
ルーチン作成の構文は、プロシージャと関数で多少異なります:
関数は値を返すため、関数定義には戻り値のデータ型を示すRETURNS句が必要です。また、呼び出し元に値を返すには、関数本体内に少なくとも1つのRETURNステートメントが必要です。 RETURNSおよびRETURNは、プロシージャ定義には表示されません。
ストアドプロシージャを呼び出すには、CALL statement
を使用します。ストアド関数を呼び出すには、式でそれを参照します。この関数は、式の評価中に値を返します。
プロシージャはCALLステートメントを使用して呼び出され、出力変数を使用してのみ値を返すことができます。関数は、他の関数と同じように(つまり、関数の名前を呼び出すことにより)ステートメント内から呼び出すことができ、スカラー値を返すことができます。
パラメーターをIN、OUT、またはINOUTとして指定することは、PROCEDUREに対してのみ有効です。 FUNCTIONの場合、パラメーターは常にINパラメーターと見なされます。
パラメーター名の前にキーワードが指定されていない場合、デフォルトでINパラメーターになります。 ストアド関数のパラメーターの前にIN、OUT、またはINOUTはありません。すべての関数パラメーターはINパラメーターとして扱われます。
ストアドプロシージャまたは関数を定義するには、それぞれCREATE PROCEDUREまたはCREATE FUNCTIONを使用します:
CREATE PROCEDURE proc_name ([parameters])
[characteristics]
routine_body
CREATE FUNCTION func_name ([parameters])
RETURNS data_type // diffrent
[characteristics]
routine_body
ストアドプロシージャ(関数ではない)のMySQL拡張機能は、プロシージャが結果セット、または複数の結果セットを生成できることであり、呼び出し元はSELECTステートメントの結果と同じ方法で処理します。ただし、そのような結果セットの内容を式で直接使用することはできません。
ストアドルーチン(ストアドプロシージャとストアド関数の両方を参照)は、テーブルまたはviews。データベースを削除すると、データベース内のストアドルーチンもすべて削除されます。
ストアドプロシージャと関数は同じ名前空間を共有しません。データベース内に同じ名前のプロシージャと関数を持つことができます。
ストアドプロシージャでは動的SQLを使用できますが、関数またはトリガーでは使用できません。
SQL準備済みステートメント(PREPARE、EXECUTE、DEALLOCATE PREPARE)は、ストアドプロシージャで使用できますが、ストアドファンクションまたはトリガーでは使用できません。したがって、ストアド関数とトリガーは動的SQLを使用できません(ステートメントを文字列として構築してから実行します)。 (MySQLストアドルーチンの動的SQL)
FUNCTIONとSTORED PROCEDUREのさらに興味深い違い:
(このポイントは ブログ投稿からコピーされた 。)ストアドプロシージャはプリコンパイルされた実行計画であり、関数はそうではありません。実行時に解析およびコンパイルされた関数。ストアドプロシージャ、データベースに擬似コードとして、つまりコンパイルされた形式で保存されます。
(この点についてはわかりません。)
ストアドプロシージャにはセキュリティがあり、ネットワークトラフィックを軽減します。また、ストアドプロシージャを呼び出すことができます。一度にアプリケーションの。 参照
関数は通常、計算に使用されますが、プロシージャは通常、ビジネスロジックの実行に使用されます。
関数はデータベースの状態に影響を与えることはできません(明示的または暗黙的なコミットまたはロールバックを行うステートメントは機能上許可されません)ストアドプロシージャはコミットなどを使用してデータベースの状態に影響を与える可能性があります.
refrence: J.1。ストアドルーチンとトリガーの制限
関数は FLUSH ステートメントを使用できませんが、ストアドプロシージャは使用できます。
ストアドプロシージャは再帰できますが、ストアドファンクションは再帰できません。注:再帰ストアドプロシージャはデフォルトでは無効になっていますが、max_sp_recursion_depthサーバーシステム変数をゼロ以外の値に設定することにより、サーバー上で有効にできます。詳細については、 セクション5.2.3、「システム変数」 を参照してください。
ストアド関数またはトリガー内では、関数またはトリガーを呼び出したステートメントによって既に(読み取りまたは書き込み用に)使用されているテーブルを変更することはできません。良い例: MYSQLで削除時に同じテーブルを更新する方法?
注:ストアドプロシージャではなく、ストアドファンクションとトリガーに通常いくつかの制限が適用されますが、これらの制限は内部から呼び出された場合、ストアドプロシージャに適用されますストアド関数またはトリガー。たとえば、ストアドプロシージャでFLUSHを使用できますが、そのようなストアドプロシージャはストアドファンクションまたはトリガから呼び出すことはできません。
大きな違いの1つは、SQLクエリに function を含めることができることですが、 ストアドプロシージャ は CALL
ステートメントでのみ呼び出すことができます。
UDFの例:
CREATE FUNCTION hello (s CHAR(20))
RETURNS CHAR(50) DETERMINISTIC
RETURN CONCAT('Hello, ',s,'!');
Query OK, 0 rows affected (0.00 sec)
CREATE TABLE names (id int, name varchar(20));
INSERT INTO names VALUES (1, 'Bob');
INSERT INTO names VALUES (2, 'John');
INSERT INTO names VALUES (3, 'Paul');
SELECT hello(name) FROM names;
+--------------+
| hello(name) |
+--------------+
| Hello, Bob! |
| Hello, John! |
| Hello, Paul! |
+--------------+
3 rows in set (0.00 sec)
Sprocの例:
delimiter //
CREATE PROCEDURE simpleproc (IN s CHAR(100))
BEGIN
SELECT CONCAT('Hello, ', s, '!');
END//
Query OK, 0 rows affected (0.00 sec)
delimiter ;
CALL simpleproc('World');
+---------------------------+
| CONCAT('Hello, ', s, '!') |
+---------------------------+
| Hello, World! |
+---------------------------+
1 row in set (0.00 sec)
ストアド関数はクエリ内で使用できます。その後、すべての行に適用するか、WHERE句内で適用できます。
CALLクエリを使用してプロシージャが実行されます。
ストアドプロシージャは再帰的に呼び出すことができますが、ストアドファンクションはできません