関数とストアドプロシージャをかなり長い間学習してきましたが、関数またはストアドプロシージャを使用する理由と時期がわかりません。彼らは私には同じように見えます、おそらく私はそれについてちょっと初心者だからです。
誰かが理由を教えてもらえますか?
関数とストアドプロシージャをかなり長い間学習してきましたが、関数またはストアドプロシージャを使用する理由と時期がわかりません。彼らは私には同じように見えます、おそらく私はそれについてちょっと初心者だからです。
誰かが理由を教えてもらえますか?
関数は計算された値であり、永続的な環境変更を実行することはできませんSQL Server
(つまり、noINSERT
またはUPDATE
ステートメントが許可されます)。
関数SQL
は、スカラー値を返す場合はステートメントでインラインで使用でき、結果セットを返す場合は結合できます。
答えをまとめたコメントから注目すべき点。@Sean K Andersonに感謝します:
関数は、値を返さなければならず、パラメーター(引数)として受け取るデータを変更できないという点で、コンピューターサイエンスの定義に従います。関数は何も変更できず、少なくとも1つのパラメーターが必要であり、値を返す必要があります。ストアドプロシージャはパラメータを持っている必要はなく、データベースオブジェクトを変更でき、値を返す必要もありません。
The difference between SP and UDF is listed below:
Stored Procedure (SP) | Function (UDF - User Defined) |
---|---|
SP can return zero, single or multiple values. | Function must return a single value (which may be a scalar or a table). |
We can use transaction in SP. | We can't use transaction in UDF. |
SP can have input/output parameter. | Only input parameter. |
We can call function from SP. | We can't call SP from function. |
We can't use SP in SELECT/ WHERE/ HAVING statement. | We can use UDF in SELECT/ WHERE/ HAVING statement. |
We can use exception handling using Try-Catch block in SP. | We can't use Try-Catch block in UDF. |
関数とストアドプロシージャは別々の目的を果たします。これは最良の例えではありませんが、関数は文字通り、プログラミング言語で使用する他の関数と同じように表示できますが、ストアドプロシージャは、個々のプログラムやバッチスクリプトに似ています。
関数には通常、出力とオプションで入力があります。次に、出力を別の関数(DATEDIFF、LENなどの組み込みのSQL Server)への入力として、またはSQLクエリの述語として使用できます(例:SELECT a, b, dbo.MyFunction(c) FROM table
または)SELECT a, b, c FROM table WHERE a = dbo.MyFunc(c)
。
ストアドプロシージャは、SQLクエリをトランザクションでバインドし、外部とのインターフェイスをとるために使用されます。ADO.NETなどのフレームワークは、関数を直接呼び出すことはできませんが、ストアドプロシージャを直接呼び出すことはできます。
ただし、関数には隠れた危険性があります。関数は誤用され、かなり厄介なパフォーマンスの問題を引き起こす可能性があります。次のクエリを検討してください。
SELECT * FROM dbo.MyTable WHERE col1 = dbo.MyFunction(col2)
MyFunctionが次のように宣言されている場合:
CREATE FUNCTION MyFunction (@someValue INTEGER) RETURNS INTEGER
AS
BEGIN
DECLARE @retval INTEGER
SELECT localValue
FROM dbo.localToNationalMapTable
WHERE nationalValue = @someValue
RETURN @retval
END
ここで何が起こるかというと、関数MyFunctionがテーブルMyTableのすべての行に対して呼び出されるということです。MyTableに1000行ある場合、それはデータベースに対する別の1000アドホッククエリです。同様に、列仕様で指定されたときに関数が呼び出されると、SELECTによって返される行ごとに関数が呼び出されます。
したがって、関数の記述には注意が必要です。関数内のテーブルからSELECTを実行する場合は、親ストアドプロシージャのJOINまたはその他のSQL構造(CASE ... WHEN ... ELSE ...など)を使用してSELECTを実行する方がよいかどうかを自問する必要があります。終わり)。
ストアドプロシージャとユーザー定義関数の違い:
RAISEERROR
または@@ERROR
、UDFでは許可されていません。GETDATE()
、UDFでは使用できません。他のSQLステートメントで使用する値を計算して返す場合は、ユーザー定義関数を記述します。代わりに、複雑な可能性のあるSQLステートメントのセットをグループ化する必要がある場合は、ストアドプロシージャを記述します。結局のところ、これらは2つのまったく異なるユースケースです。
ストアドプロシージャ | 関数(ユーザー定義関数) |
---|---|
プロシージャは0、単一または複数の値を返すことができます | 関数は単一の値のみを返すことができます |
プロシージャには、入力パラメータと出力パラメータを含めることができます | 関数は入力パラメーターのみを持つことができます |
関数からプロシージャを呼び出すことはできません | プロシージャから関数を呼び出すことができます |
プロシージャでは、DMLステートメントだけでなくselectステートメントも使用できます | 関数はその中のselectステートメントのみを許可します |
例外は、プロシージャのtry-catchブロックで処理できます | Try-catchブロックは関数で使用できません |
手順でトランザクション管理に行くことができます | 機能的にトランザクション管理に行くことはできません |
プロシージャをselectステートメントで使用することはできません | 関数はselectステートメントに埋め込むことができます |
手順はデータベースの状態に影響を与える可能性があります。つまり、データベースに対してCRUD操作を実行できます。 | 関数がデータベースの状態に影響を与えることができないということは、データベースに対してCRUD操作を実行できないことを意味します |
プロシージャは一時テーブルを使用できます | 関数は一時テーブルを使用できません |
手順により、サーバー環境パラメーターが変更される可能性があります | 関数は環境パラメータを変更できません |
代わりに、複雑な可能性のあるSQLステートメントのセットをグループ化する場合に使用できるプロシージャ | 関数は、他のSQLステートメントで使用する値を計算して返す場合に使用できます |
基本的な違い
関数は値を返す必要がありますが、ストアドプロシージャではオプションです(プロシージャはゼロまたはn個の値を返すことができます)。
関数はその入力パラメーターのみを持つことができますが、プロシージャは入力/出力パラメーターを持つことができます。
関数は1つの入力パラメーターを取りますが、これは必須ですが、ストアード・プロシージャーはoからnの入力パラメーターを取る場合があります。
関数はプロシージャから呼び出すことができますが、プロシージャは関数から呼び出すことはできません。
事前差
プロシージャではSELECTステートメントとDML(INSERT / UPDATE / DELETE)ステートメントを使用できますが、ファンクションではSELECTステートメントのみを使用できます。
プロシージャはSELECTステートメントで使用できませんが、FunctionはSELECTステートメントに埋め込むことができます。
ストアドプロシージャは、WHERE / HAVING / SELECTセクションのSQLステートメントでは使用できませんが、関数では使用できます。
テーブルを返す関数は、別の行セットとして扱うことができます。これは、他のテーブルとのJOINで使用できます。
インライン関数は、パラメーターを受け取り、JOINやその他の行セット操作で使用できるビューと考えることができます。
例外は、プロシージャのtry-catchブロックで処理できますが、関数ではtry-catchブロックは使用できません。
手続きではトランザクション管理に進むことができますが、機能では行くことができません。
ユーザー定義関数は、SQLサーバープログラマーが利用できる重要なツールです。次のようなSQLステートメントでインラインで使用できます。
SELECT a, lookupValue(b), c FROM customers
lookupValue
UDFはどこになりますか。ストアドプロシージャを使用する場合、この種の機能は使用できません。同時に、UDF内で特定のことを行うことはできません。ここで覚えておくべき基本的なことは、UDFの次のことです。
ストアドプロシージャはそれらのことを実行できます。
私にとって、UDFのインライン使用はUDFの最も重要な使用法です。
ストアドプロシージャ はスクリプトとして使用されます。彼らはあなたのために一連のコマンドを実行し、あなたはそれらを特定の時間に実行するようにスケジュールすることができます。通常、INSERT、UPDATE、DELETEなどの複数のDMLステートメント、またはSELECTを実行します。
関数 はメソッドとして使用されます。あなたはそれに何かを渡すと、それは結果を返します。小さくて速いはずです-その場でそれを行います。通常、SELECTステートメントで使用されます。
ストアドプロシージャ:
EXEC
またはEXECUTE
ステートメントを使用して呼び出す必要があります。OUT
テーブル変数を返しますが、パラメータは使用できません。働き:
レコードの選択にのみ使用できます。ただし、次のように、標準SQL内から非常に簡単に呼び出すことができます。
SELECT dbo.functionname('Parameter1')
また
SELECT Name, dbo.Functionname('Parameter1') FROM sysObjects
単純な再利用可能な選択操作の場合、関数はコードを単純化できます。JOIN
関数で句を使用する場合は注意が必要です。関数にJOIN
句があり、複数の結果を返す別のselectステートメントからそれを呼び出す場合、その関数呼び出しは、結果セットで返される行ごとJOIN
に
それらのテーブルをまとめて呼び出します。したがって、これらは一部のロジックを単純化するのに役立ちますが、適切に使用されていない場合、パフォーマンスのボトルネックになる可能性もあります。
OUT
ます。ユーザー定義関数。
ストアドプロシージャ
カーソルのようなSQLServer関数は、最後の武器として使用することを目的としています。それらにはパフォーマンスの問題があるため、テーブル値関数の使用は可能な限り避ける必要があります。パフォーマンスについて話すことは、ミドルクラスのハードウェア上のサーバーでホストされている1,000,000を超えるレコードを持つテーブルについて話すことです。それ以外の場合は、関数によって引き起こされるパフォーマンスの低下について心配する必要はありません。
詳細については、http: //databases.aspfaq.com/database/should-i-use-a-view-a-stored-procedure-or-a-user-defined-function.htmlを参照してください。
次のポイントが役立つ可能性があるものをいつ使用するかを決定するには-
ストアドプロシージャはテーブル変数を返すことができませんが、関数はそれを行うことができます。
ストアドプロシージャを使用してサーバー環境パラメータを変更できますが、関数を使用する場合は変更できません。
乾杯
単一の値を返す関数から始めます。良い点は、頻繁に使用するコードを関数に入れて、結果セットの列として返すことができることです。
次に、パラメータ化された都市のリストの関数を使用できます。dbo.GetCitiesIn( "NY")これは結合として使用できるテーブルを返します。
これは、コードを整理する方法です。いつ再利用可能で、いつそれが時間の無駄であるかを知ることは、試行錯誤と経験によってのみ得られるものです。
また、SQLServerでは関数を使用することをお勧めします。それらはより高速で、非常に強力です。インラインおよび直接選択。使いすぎないように注意してください。
ストアドプロシージャよりも関数を優先する実際的な理由は次のとおりです。別のストアドプロシージャの結果を必要とするストアドプロシージャがある場合は、insert-execステートメントを使用する必要があります。これは、一時テーブルを作成し、exec
ステートメントを使用してストアドプロシージャの結果を一時テーブルに挿入する必要があることを意味します。散らかっています。これに関する1つの問題は、insert-execをネストできないことです。
他のストアドプロシージャを呼び出すストアドプロシージャで立ち往生している場合は、これに遭遇する可能性があります。ネストされたストアドプロシージャが単にデータセットを返す場合は、テーブル値関数に置き換えることができ、このエラーは発生しなくなります。
(これは、ビジネスロジックをデータベースから除外する必要があるもう1つの理由です)
これは非常に古い質問だと思いますが、どの回答にも重要な側面が1つはありません。それは、クエリプランにインライン化することです。
関数は...
スカラー:
CREATE FUNCTION ... RETURNS scalar_type AS BEGIN ... END
マルチステートメントテーブル値:
CREATE FUNCTION ... RETURNS @r TABLE(...) AS BEGIN ... END
インラインテーブル値:
CREATE FUNCTION ... RETURNS TABLE AS RETURN SELECT ...
3番目の種類(インラインテーブル値)は、クエリオプティマイザーによって基本的に(パラメーター化された)ビューとして扱われます。つまり、クエリから関数を参照することは、関数のSQL本体を(実際にコピーして貼り付けることなく)コピーして貼り付けることに似ています。次の利点があります。
上記は、特に複数のレベルの機能を組み合わせる場合に、潜在的に大幅なパフォーマンスの低下につながる可能性があります。
注:SQL Server 2019では、何らかの形式のスカラー関数のインライン化も導入されるようです。
関数はselectステートメントで使用できますが、プロシージャでは使用できません。
ストアドプロシージャは入力パラメータと出力パラメータの両方を取りますが、関数は入力パラメータのみを取ります。
関数は、プロシージャができる場合、タイプtext、ntext、image、およびタイムスタンプの値を返すことはできません。
関数は、テーブルの作成でユーザー定義のデータ型として使用できますが、プロシージャは使用できません。
***例:-作成table <tablename>(name varchar(10),salary getsal(name))
ここで、getsalは給与タイプを返すユーザー定義関数であり、テーブルが作成されると、給与タイプにストレージが割り当てられず、getsal関数も実行されませんが、このテーブルからいくつかの値をフェッチすると、getsal関数getが実行され、 returnTypeが結果セットとして返されます。
一般に、パフォーマンスにはストアドプロシージャを使用する方が適しています。たとえば、以前のバージョンのSQL Serverでは、関数をJOIN条件にすると、カーディナリティの推定値は1(SQL 2012より前)および100(SQL2012より後およびSQL2017より前)であり、エンジンは不適切な実行プランを生成する可能性があります。
また、WHERE句に入れると、SQLエンジンが不正な実行プランを生成する可能性があります。
SQL 2017で、Microsoftはより正確な見積もりを生成するためにインターリーブ実行と呼ばれる機能を導入しましたが、ストアドプロシージャは依然として最良のソリューションです。
詳細については、JoeSackの次の記事を参照して くださいhttps://techcommunity.microsoft.com/t5/sql-server/introducing-interleaved-execution-for-multi-statement-table/ba-p/385417
SQL Serverでは、関数とストアドプロシージャは2つの異なるタイプのエンティティです。
関数: SQL Serverデータベースでは、関数はいくつかのアクションを実行するために使用され、アクションはすぐに結果を返します。関数には2つのタイプがあります。
システム定義
ユーザー定義の
ストアドプロシージャ: SQL Serverでは、ストアドプロシージャはサーバーに格納され、ゼロ、単一、および複数の値を返すことができます。ストアドプロシージャには次の2つのタイプがあります。