2012-09-26 16 views
7

テーブル値関数構文を使用せずに複数の値を返すSQL ServerのCLRユーザー定義関数を作成する方法はありますか?たとえば、次のような座標変換を実行したいとします。Outパラメーターを使用したSQL Server CLR UDF - これは可能ですか?

[SqlFunction()] 
public void ConvertCoordinates(SqlDouble x, SqlDouble y, SqlDouble z, out SqlDouble r, out SqlDouble t, out SqlDouble p) 
{ 
    r = new SqlDouble(Math.Sqrt((x.Value*x.Value)+(y.Value*y.Value)+(z.Value*z.Value))); 
    t = new SqlDouble(Math.Acos(r.Value/z.Value)); 
    p = new SqlDouble(Math.Atan(y.Value/x.Value)); 
} 

これも可能ですか?計算では複数の出力行が生成されないため、この場合のテーブル値関数は不適切です。スカラー値の関数構文を使用して、私は計算を実行し、それぞれを別々に呼び出すために3つの異なる関数を書く必要があります。私の実際のユースケースを考えると、これは非常に実用的ではありません。

私は、上記のロジックは純粋なT-SQLを使用して達成できることを認識しています。私の実際のユースケースはより複雑ですが、依然として複数の相互依存する出力値を持つ単一の行だけになります。

だから、結論は実現可能ですか?私はそうは思わないが、誰かが望むことができる。偶然に実現可能なら、そのような関数を呼び出すT-SQLの外観はどうでしょうか?すでにCLRプランジを撮影したので、私はそれを試していないが、私はT-SQLを希望想像認める

+1

UDF(スカラー型、表型、T-SQL型、CLR型)は、パラメータを持つことができません。可能であれば、これらの出力を消費したい場合は、 'SELECT'節で呼び出すための新しい構文を作成する必要があります。そして、私はなぜあなたが奇妙に見えるはずのテーブル値の関数が単一の行を返すのか分かりません。 –

+1

@Damienこれは単にそれが可能かどうかの問題でした。私の読書と実験では、それはおそらく(私も述べたように)そうではないことが示されていましたが、私はCLRの統合を初めて知りましたので、私は尋ねたいと思っていました。 1行以上の可能性がある場合、TVFは「私にとって奇妙な」とは思われません。この例では、常に1行を返しますが、関連する戻り値はセットとしてのみ意味があります。私の実際のユースケースでは、何百万もの行に対して同様の、しかしより大きな計算を実行しています。したがって、パラメータが可能である場合、TVFは非効率的に見えます。シンプルな「いいえ」で十分でした。 – bporter

+0

@bporter - 明らかに、TVFが最善の選択肢になるでしょう - あなたはそれを自分で言うのです。彼らは "1行以上の可能性があるときは奇妙に見えません"と言い、何百万行もあると言います。 Ergo a(S)TVFが答えです!それは、命令的なforeachステートメントのように、すべての行を反復処理するより効率的になるでしょう。 – gbjbaanb

答えて

3

、あなた自身のCLR型を作成することができたことができますとあらゆる種類の狂気のことをする。実用的な例として、HierarchyIDと同様に、ネイティブ空間タイプがこのように実装されています。独自の型を定義したら、関数がそれを返すようにすることができます。個々のコンポーネントを取得する場合(私があなたのケースの半径、シータ、およびファイを想定している場合)、それを返すタイプのメソッドを作成します。

+0

提案していただきありがとうございます。 UDTはこれをはるかに単純化し、私はそれらを調べました。私が持っていた唯一の懸念は、すべてのデータベースにアセンブリを登録する必要があることでした。私の場合、私は過去10年間に蓄積された何百ものデータベースのデータを採掘しています。 UDFは1つのデータベースに配置し、他のデータベースから呼び出して計算を実行できるため、よりシンプルに見えました。各データベースにアセンブリを登録せずに、空間タイプと同様にすべてのデータベースでUDTを使用できるようにする方法がありますか? – bporter

+0

私はいくつかのアプローチについて考えることができます。 1つ目は、1つのdbに1回登録するだけで、そのdbのコンテキストですべてのデータ収集を行う場合です。もう1つはどこにでも展開することです。それはT-SQLなので、おそらくすべてのdbに対してコードを実行する方法があると思われますが、これは問題ではありません。 DLLをどこにでもデプロイする必要はなく、スクリプト内でビットストリームを介してアセンブリをデプロイすることができます。 –

-1

DECLARE @X FLOAT(53), 
     @Y FLOAT(53), 
     @Z FLOAT(53), 
     @R FLOAT(53), 
     @T FLOAT(53), 
     @P FLOAT(53) 

EXEC ConvertCoordinates 
     @X = 0, 
     @Y = 0, 
     @Z = 0, 
     @R = @R OUTPUT, 
     @T = @T OUTPUT 
     @P = @P OUTPUT 
1

これは古い質問であり、非常によく似た質問に対する回答を探していました。

SQL関数は戻り値を許可しますが、出力パラメータは使用できません。

http://technet.microsoft.com/en-us/library/ms131092.aspx

[Microsoft.SqlServer.Server.SqlProcedure] 
public static void PriceSum(out SqlInt32 value) 
{ … } 

CREATE PROCEDURE PriceSum (@sum int OUTPUT) 
AS EXTERNAL NAME TestStoredProc.StoredProcedures.PriceSum 

:出力パラメータ(ただし、戻り値は)

私はここにMSDNの例からこれを見つけたことができない

SQLプロシージャ私が関数をプロシージャに登録しようとしたときに切り替わったときすべてがうまくいくかどうか。関数は戻り値を持つことができますが、ストアドプロシージャは返すことができません。私の場合は、文字列値を返していて、状態コードなどのオプションの詳細情報の出力パラメータを持っていました。私のやり方は、メソッドをvoidに変更し、文字列値を出力パラメータとして渡しました。

あなたのメソッドは、とにかくvoidで戻り値がないため、関数の代わりにストアドプロシージャを使用するのに最適な候補です。

関連する問題