MySQLストアドプロシージャと関数のどちらを使用しますか?


160

MySQLのストアドプロシージャと関数を調べています。本当の違いは何ですか?

それらは似ているように見えますが、関数にはさらに制限があります。

私は間違っている可能性がありますが、ストアドプロシージャですべてを実行でき、さらにストアドファンクションで実行できるようです。なぜ/いつプロシージャと関数を使用するのですか?

回答:


101

ストアドプロシージャを通常のSQLと混在させることはできませんが、ストアドファンクションを混在させることはできます。

たとえばSELECT get_foo(myColumn) FROM mytableget_foo()プロシージャの場合は無効ですget_foo()が、関数の場合はそれを実行できます。その代償として、関数にはプロシージャよりも多くの制限があります。


18
関数にはどのような制限がありますか?
ファンティウス、

11
ああ、私はここにいくつかの良い情報を見つけました: dev.mysql.com/doc/refman/5.0/en/...
Fantius

262

プロシージャと関数の最も一般的な違いは、それらが異なる方法で、異なる目的で呼び出されることです。

  1. プロシージャは値を返しません。代わりに、CALLステートメントを使用して呼び出され、テーブルの変更や取得したレコードの処理などの操作を実行します。
  2. 関数は式内で呼び出され、式で使用される単一の値を呼び出し元に直接返します。
  3. CALLステートメントで関数を呼び出すことはできません。また、式でプロシージャを呼び出すこともできません。

ルーチン作成の構文は、手順と関数で多少異なります。

  1. プロシージャパラメータは、入力のみ、出力のみ、またはその両方として定義できます。これは、プロシージャが出力パラメータを使用して値を呼び出し元に返すことができることを意味します。これらの値は、CALLステートメントに続くステートメントでアクセスできます。関数には入力パラメーターのみがあります。その結果、プロシージャと関数の両方にパラメータを設定できますが、プロシージャのパラメータ宣言は関数の場合と異なります。
  2. 関数は値を返すので、関数定義には戻り値のデータ型を示す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ステートメントの結果と同じ方法で処理します。ただし、そのような結果セットの内容を式で直接使用することはできません。

ストアドルーチンストアドプロシージャとストアドファンクションの両方を指す)は、テーブルやビューと同じように、特定のデータベースに関連付けられています。データベースを削除すると、データベース内のストアドルーチンもすべて削除されます。

ストアドプロシージャと関数は同じ名前空間を共有しません。データベースに同じ名前のプロシージャと関数を含めることができます。

ストアドプロシージャでは、動的SQLを使用できますが、関数やトリガーでは使用できません。

SQL準備済みステートメント(PREPARE、EXECUTE、DEALLOCATE PREPARE)は、ストアード・プロシージャーで使用できますが、ストアード関数またはトリガーでは使用できません。したがって、ストアドファンクションとトリガーはダイナミックSQLを使用できません(ステートメントを文字列として作成し、実行する場合)。(MySQLストアドルーチンの動的SQL)

FUNCTIONとSTORED PROCEDUREのさらに興味深い違い:

  1. このポイントはブログ投稿からコピーされます。)ストアドプロシージャは、関数が含まれていないプリコンパイルされた実行プランです。実行時に解析およびコンパイルされる関数。ストアドプロシージャ。データベースに擬似コードとして格納されます(つまり、コンパイルされた形式)。

  2. この点
    についてはわかりません。)ストアドプロシージャはセキュリティが確保されており、ネットワークトラフィックを軽減します。また、ストアドプロシージャをどの番号でも呼び出すことができます。一度にアプリケーションの。参照

  3. 関数は通常、計算に使用されますが、プロシージャは通常、ビジネスロジックの実行に使用されます。

  4. ストアドプロシージャを使用してコミットなどのデータベースの状態に影響を与えることができるのに対し機能は、データベース(明示的または暗黙的なコミットか、またはロールバック機能で禁止されているステートメント)の状態に影響を与えることができない
    refrenceを:J.1を。ストアドルーチンとトリガーの制限

  5. 関数はFLUSHステートメントを使用できませんが、ストアドプロシージャは使用できます。

  6. ストアドプロシージャは再帰可能ですが、ストアドファンクションは再帰的ではありません。注:再帰ストアード・プロシージャーはデフォルトで無効になっていますが、サーバーでmax_sp_recursion_depthサーバー・システム変数をゼロ以外の値に設定することで有効にできます。詳細については、セクション5.2.3「システム変数」を参照してください。

  7. ストアドファンクションまたはトリガー内では、関数またはトリガーを呼び出したステートメントによって(読み取りまたは書き込みのために)既に使用されているテーブルを変更することはできません。良い例:MYSQLで削除時に同じテーブルを更新する方法は?

:通常、一部の制限はストアドファンクションとトリガーに適用されますが、ストアドプロシージャには適用されませんが、ストアドファンクションまたはトリガー内から呼び出された場合、それらの制限はストアドプロシージャに適用されます。たとえば、ストアドプロシージャでFLUSHを使用できますが、そのようなストアドプロシージャは、ストアドファンクションまたはトリガーから呼び出すことはできません。


2
@GrijeshChauhan、「実行時に解析およびコンパイルされた関数」とはどういう意味ですか?
Pacerier、2015年

@Pacerierは、MySQLの関数がオンザフライでコンパイルおよび実行されるスクリプトのようなものであることを意味します。私はいくつかのブログ投稿からそれをコピーしましたが、この動作を検査するための実用的なことは何もしませんでした。
Grijesh Chauhan、2015

プロシージャでは、out変数をパラメーターとして渡し、selectステートメントで呼び出すことができます
LTroya

1
この回答の一番下のセクションの箇条書き#4は、手順と関数の違いの核心だと思います。プロシージャはデータベースを変更できますが、関数はできません。他のすべての違いは、単にその目的をより効果的に果たすためです。
Woodrow Barlow

51

重要な違いの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)

1
あなたの関数には2つの戻りがありますか?この行は何ですか?RETURNS CHAR(50) DETERMINISTIC
マーティンAJ

RETURNS CHAR(50)状態は、データの種類が返されます。RETURN CONCAT(...返されるデータです。両方が必要です。DETERMINISTIC基になるデータが変更されない状態に必要とされています。
lemming622

8

ストアド関数はクエリ内で使用できます。次に、それをすべての行に、またはWHERE句内に適用できます。

プロシージャはCALLクエリを使用して実行されます。


0

ストアドプロシージャは再帰的に呼び出すことができますが、ストアドファンクションはできません

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.