190

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

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

私はおそらく間違っていますが、ストアドプロシージャはすべてを実行でき、ストアド関数よりも多くのことを実行できるようです。なぜ/いつプロシージャと関数を使用するのですか?

4

6 に答える 6

300

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

  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パラメーターとして扱われます。

ストアドプロシージャまたは関数を定義するには、それぞれ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のいくつかの興味深い違い:

  1. この点はブログ投稿からコピーされています)ストアドプロシージャはプリコンパイルされた実行プランですが、関数はそうではありません。関数実行時に解析およびコンパイルされます。ストアドプロシージャ。データベースに疑似コードとして保存されます。つまり、コンパイルされた形式です。

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

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

  4. 関数はデータベースの状態に影響を与えることはできません(明示的または暗黙的なコミットまたはロールバックを行うステートメントは関数では許可されていません)一方、ストアドプロシージャはコミットなどを使用してデータベースの状態に影響を与える可能性があり
    ます。保存されたルーチンとトリガーの制限

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

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

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

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

于 2012-11-22T10:01:19.833 に答える
122

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

たとえば、がプロシージャのSELECT get_foo(myColumn) FROM mytable場合は無効ですが、が関数の場合は有効です。価格は、関数には手順よりも多くの制限があるということです。get_foo()get_foo()

于 2010-09-19T01:58:40.577 に答える
57

重要な違いの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)
于 2010-09-19T01:59:14.273 に答える
9

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

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

于 2010-09-19T01:54:38.650 に答える
0

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

于 2018-08-14T05:48:03.283 に答える
0

上記の答えのほかに、それを追加したいと思います

関数は、他の関数や式と組み合わせて使用​​することも、ネストされた方法で使用することもできます(つまり、非常に複雑な形式で使用して、必要な作業を実行できます)。

同じことをプロシージャで実装できますが、プロシージャでは、そのプロシージャ内で行われるすべての作業を実行する必要がありました。つまり、モノリシックな方法でコードを実行する必要がありました。(関数内はすべてのタスクに使用できますが、新しい関数を実装できます)。したがって、最後に、さまざまな機能の組み合わせを使用してタスクを実行できます。

于 2021-07-01T11:18:50.123 に答える