MySQLのストアドプロシージャと関数を見ています。本当の違いは何ですか?
それらは似ているように見えますが、関数にはさらに多くの制限があります。
私はおそらく間違っていますが、ストアドプロシージャはすべてを実行でき、ストアド関数よりも多くのことを実行できるようです。なぜ/いつプロシージャと関数を使用するのですか?
MySQLのストアドプロシージャと関数を見ています。本当の違いは何ですか?
それらは似ているように見えますが、関数にはさらに多くの制限があります。
私はおそらく間違っていますが、ストアドプロシージャはすべてを実行でき、ストアド関数よりも多くのことを実行できるようです。なぜ/いつプロシージャと関数を使用するのですか?
プロシージャと関数の最も一般的な違いは、それらが異なる目的で異なる方法で呼び出されることです。
ルーチン作成の構文は、プロシージャと関数によって多少異なります。
関数は値を返すため、戻り値のデータ型を示すために関数定義にRETURNS句が必要です。また、呼び出し元に値を返すには、関数本体内に少なくとも1つのRETURNステートメントが必要です。RETURNSおよびRETURNは、プロシージャー定義には表示されません。
ストアドプロシージャを呼び出すには、を使用しCALL statement
ます。ストアド関数を呼び出すには、式でそれを参照します。この関数は、式の評価中に値を返します。
プロシージャはCALLステートメントを使用して呼び出され、出力変数を使用してのみ値を返すことができます。関数は、他の関数と同じように(つまり、関数の名前を呼び出すことによって)ステートメント内から呼び出すことができ、スカラー値を返すことができます。
パラメーターをIN、OUT、またはINOUTとして指定することは、PROCEDUREに対してのみ有効です。FUNCTIONの場合、パラメーターは常にINパラメーターと見なされます。
パラメータ名の前にキーワードが指定されていない場合、デフォルトではINパラメータです。 保存された関数のパラメーターの前には、IN、OUT、またはINOUTはありません。すべての関数パラメーターはINパラメーターとして扱われます。
ストアドプロシージャまたは関数を定義するには、それぞれCREATEPROCEDUREまたはCREATEFUNCTIONを使用します。
CREATE PROCEDURE proc_name ([parameters])
[characteristics]
routine_body
CREATE FUNCTION func_name ([parameters])
RETURNS data_type // diffrent
[characteristics]
routine_body
ストアドプロシージャ(関数ではない)のMySQL拡張機能は、プロシージャが結果セット、または複数の結果セットを生成できることです。これは、呼び出し元がSELECTステートメントの結果と同じ方法で処理します。ただし、このような結果セットの内容を式で直接使用することはできません。
ストアドルーチン(ストアドプロシージャとストアド関数の両方を参照)は、テーブルやビューと同様に、特定のデータベースに関連付けられています。データベースを削除すると、データベースに保存されているルーチンもすべて削除されます。
ストアドプロシージャと関数は同じ名前空間を共有しません。データベースに同じ名前のプロシージャと関数を含めることができます。
ストアドプロシージャでは、動的SQLを使用できますが、関数やトリガーでは使用できません。
SQLプリペアドステートメント(PREPARE、EXECUTE、DEALLOCATE PREPARE)は、ストアドプロシージャで使用できますが、ストアド関数またはトリガーでは使用できません。したがって、格納された関数とトリガーは動的SQLを使用できません(ステートメントを文字列として作成してから実行する場合)。(MySQLストアドルーチンの動的SQL)
FUNCTIONとSTOREDPROCEDUREのいくつかの興味深い違い:
(この点はブログ投稿からコピーされています。)ストアドプロシージャはプリコンパイルされた実行プランですが、関数はそうではありません。関数実行時に解析およびコンパイルされます。ストアドプロシージャ。データベースに疑似コードとして保存されます。つまり、コンパイルされた形式です。
(この点についてはよくわかりません。)
ストアドプロシージャにはセキュリティがあり、ネットワークトラフィックが削減されます。また、ストアドプロシージャを任意の番号で呼び出すことができます。一度にアプリケーションの。参照
関数は通常、計算に使用されますが、プロシージャは通常、ビジネスロジックの実行に使用されます。
関数はデータベースの状態に影響を与えることはできません(明示的または暗黙的なコミットまたはロールバックを行うステートメントは関数では許可されていません)一方、ストアドプロシージャはコミットなどを使用してデータベースの状態に影響を与える可能性があり
ます。保存されたルーチンとトリガーの制限
関数はFLUSHステートメントを使用できませんが、ストアドプロシージャは使用できます。
ストアド関数は再帰的ではありませんが、ストアドプロシージャは再帰的です。注:再帰的ストアドプロシージャはデフォルトで無効になっていますが、サーバーでmax_sp_recursion_depthサーバーシステム変数をゼロ以外の値に設定することで有効にできます。詳細については、5.2.3項「システム変数」</a>を参照してください。
ストアド関数またはトリガー内で、関数またはトリガーを呼び出したステートメントによって(読み取りまたは書き込みのために)すでに使用されているテーブルを変更することは許可されていません。良い例:MYSQLでの削除時に同じテーブルを更新する方法は?
注:通常、一部の制限はストアド関数とトリガーに適用されますが、ストアドプロシージャには適用されませんが、これらの制限は、ストアド関数またはトリガー内から呼び出された場合にストアドプロシージャに適用されます。たとえば、ストアドプロシージャでFLUSHを使用することはできますが、そのようなストアドプロシージャをストアド関数またはトリガーから呼び出すことはできません。
ストアドプロシージャを通常のSQLと混在させることはできませんが、ストアド関数を混在させることはできます。
たとえば、がプロシージャのSELECT get_foo(myColumn) FROM mytable
場合は無効ですが、が関数の場合は有効です。価格は、関数には手順よりも多くの制限があるということです。get_foo()
get_foo()
重要な違いの1つは、SQLクエリに関数を含めることができることですが、ストアドプロシージャ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クエリを使用して実行されます。
ストアドプロシージャは再帰的に呼び出すことができますが、ストアド関数は呼び出すことができません
上記の答えのほかに、それを追加したいと思います
関数は、他の関数や式と組み合わせて使用することも、ネストされた方法で使用することもできます(つまり、非常に複雑な形式で使用して、必要な作業を実行できます)。
同じことをプロシージャで実装できますが、プロシージャでは、そのプロシージャ内で行われるすべての作業を実行する必要がありました。つまり、モノリシックな方法でコードを実行する必要がありました。(関数内はすべてのタスクに使用できますが、新しい関数を実装できます)。したがって、最後に、さまざまな機能の組み合わせを使用してタスクを実行できます。