web-dev-qa-db-ja.com

「ストアドプロシージャ」と「ストアドファンクション」の違いは何ですか?

この質問 からのコメントでは、PostgreSQLの「Stored Procedrues」と「Stored Funtions」にわずかな違いがあると述べています。

コメントは wikipediaの記事 にリンクしていますが、これの一部は適用されないようです(例:SELECTステートメントで使用できる)。

syntax 自体は少し混乱しているようです:

CREATE FUNCTION emp_stamp() RETURNS trigger AS $emp_stamp$
    BEGIN
       [...]
    END;
$emp_stamp$ LANGUAGE plpgsql;

CREATE TRIGGER emp_stamp BEFORE INSERT OR UPDATE ON emp
    FOR EACH ROW EXECUTE PROCEDURE emp_stamp();

FUNCTIONを作成しますが、PROCEDUREとして参照します。

では、これら2つの違いは何ですか?

37
DrColossos

公式には、PostgreSQLには「関数」しかありません。トリガー関数は「トリガープロシージャ」と呼ばれることもありますが、その使用法には明確な意味はありません。内部的には、関数は、システムカタログpg_procなどでは、プロシージャと呼ばれることがあります。それはPostQUELからの持ち越しです。 SQLインジェクションの防止や出力パラメーターの使用との関連性など、一部の人々(異なるデータベースシステムでの経験がある可能性がある)がプロシージャに関連付ける可能性のある機能も、PostgreSQLに存在する機能に適用されます。

現在、PostgreSQLコミュニティの人々が「ストアドプロシージャ」または「実際のストアドプロシージャ」について話すとき、それらはしばしば、現在の関数では実行できない、本体でトランザクションを開始および停止できる関数のようなオブジェクトの仮想的な機能を意味します行う。このコンテキストでの「ストアドプロシージャ」という用語の使用は、他のデータベース製品に類似しているようです。曖昧なアイデアについては、 このメーリングリスト スレッドを参照してください。

ただし、実際には、トランザクション制御機能に関する関数とプロシージャのこの区別は広く受け入れられておらず、データベースバイアスのない多くのプログラマーは、プロシージャを戻り値のない関数としてPascalのように解釈します。 (SQL標準は、defaultによるプロシージャが関数とは異なるトランザクション動作を持っているという点で中立的な立場にあるように見えますが、これは、オブジェクト。)したがって、いずれの場合でも、特に、非常に多種多様な対象者がいるStack Exchangeの質問を見る場合は、想定しすぎて避け、より明確な用語を使用するか、期待するプロパティを定義する必要があります。

44

DDLに関しては、Postgresにはプロシージャオブジェクトはなく、関数のみがあります。 Postgres関数は値またはvoidを返すことができるため、他のRDBMSの関数とプロシージャの両方の役割を果たします。 create triggerの「プロシージャ」という語は、関数を指します。

Postgresのドキュメントでは、「プロシージャ」は関数と呼ばれるデータベースオブジェクトの同義語でもあります。例: " トリガープロシージャはCREATE FUNCTIONコマンドで作成されます "。

トリガーの「プロシージャ」には特定のルールがあります。それらは 引数なしの関数として宣言され、トリガーの戻り型 である必要があります。例 ここ

「ストアドプロシージャ」と「ストアドファンクション」という用語は、PostgreSQLでは同じ意味で使用されており、一般的に同じ意味で使用されています。他のデータベースは、プロシージャと関数を区別する場合があります(VBがサブルーチンと関数を区別する方法と同様)。

PostgreSQLの関数がテーブルに似たものを返す限り、その関数の出力を標準のテーブルのように使用できます。 CREATE TRIGGER構文は少しわかりにくいですが、ANSI標準が完成する前に構文が整っていたのではないかと思います。私はSQL:2003のコピーしか持っていないので、命名が奇妙な理由を推測する以上のことはできません。

TL; DRバージョン:PostgreSQLでは、「プロシージャ」は「関数」と同等です。

8

MSSQLでは、ストアドプロシージャは事前にコンパイルされた一連のSQLコマンドです。
ストアドプロシージャ:

-多くの入力および出力パラメーターを持つことができます
-データベーステーブル/構造/データを変更するために使用できます
-挿入/更新/削除/選択ステートメント内では通常使用されません
-複数の入力パラメーターを持つことができますが、単一の値(つまり、文字列連結)のみを返します
-テーブルを返します(つまり、select * from dbo.ExplodeString( "this is a list of words"))
-select/insert/update/deleteステートメントで使用できます
-データベースのテーブル/構造/データの変更には使用できません
6
datagod

簡単に言えば、関数は値を返しますが、プロシージャは返しません。

その違いは、SQL 1992で提案された永続的ストアドモジュール(SQL/PSM)に存在していました。SQL/ PSMがこれを標準にしたかどうかはわかりません。

受け入れられた答えを抽象的な概念レベルから比較すると、機能性と入出力の観点からの違いがわかります。以下では、spとfを使用して、それぞれストアドプロシージャと関数を表しています。

  1. 式での使用:spは式では使用できませんが、関数では使用できます。つまり、fからの戻り値を他のステートメント内で使用できます。

    select * 
    from table 
    where col_a < (select col_A from f())
    
  2. 値を返す:refcursor戻り値の型を指定しない限り、spは自動的に値を返しません。カーソルを開いて返します。 fは、select句のように、「return」句が埋め込まれている最後のステートメントの結果を返します。

  3. 単一/複数の結果セットを返す:ここで結果セットは、単一の整数、テキスト配列、2つのテーブルのセットなど、形式が異なる可能性がある結果のリストを参照します。 spは、refcursor戻り型を指定し、カーソルを開いて返す限り、複数のセットを返すことができます。ただし、fは1つのタイプのセットのみを返すことができます。

通常、ストアドプロシージャは、delete、update、dropなど、戻り値が不要なデータベースデータまたは構造を変更するために使用されます。または、複数の結果セットが必要な状況。一方、関数は主に単純なクエリに対して選択されます。

私の説明の詳細については、このリンクを参照してください: PostgreSQLのストアドプロシージャと関数

2
Frank

PostgreSQL 11では、ストアドプロシージャが新しいスキーマオブジェクトとして追加されました。 CREATE PROCEDURE ステートメントを使用して、新しいプロシージャを作成できます。

ストアドプロシージャは、次の点で関数と異なります。

  • ストアドプロシージャに戻り値がありません
  • ストアドプロシージャ内でトランザクションをコミットおよびロールバックできますが、関数内ではできません
  • ストアドプロシージャを実行するには、CALLステートメントではなくSELECTステートメントを使用します。
1
d4nyll