2012-02-10 5 views
1

私は基本的に同じことを行うストアドプロシージャが多数あります:パラメータとして値のリストを取得し、次にいくつかのテーブルとSELECTに移動しますこれらの値が一致するすべての行。T-SQL - 不明な型の未知数のパラメータを処理するストアドプロシージャ

これらのすべてのケースを処理できる単一のストアドプロシージャを用意したいと考えています。

これにどのように対処しますか?

+7

も、このためにストアドプロシージャを使用してのポイントは何ですか?動的なSQLが必要になるため、プランのキャッシュや所有権の連鎖の恩恵を受けることはありません。それぞれのケースに対して別々のストアドプロシージャを用意するだけです。 –

+0

例を示してください。 –

+0

可変数の仮パラメータを持つ単一のsprocを現在使用できるとは思わない:http://stackoverflow.com/questions/7653405/expression-parameter-data-types-for-user-defined-functions-おそらくcodegen T4などを介して – AakashM

答えて

2

を使用して、それを呼び出すことができます。 XMLを入力パラメーターとして送信します。 xmlをテーブルに変換します。テーブルフォームから動的クエリを実行して、目的の機能を実現します。以下の例を参照してください。この例では、Departmentsは3つの列pkDepartmentId(int)、DepartmentName(varchar)およびBuildingNumber(int)を含む表です。この方法を使用すると、n個のパラメータとその値を入力パラメータとして送信できます。

pkDepartmentId DepartmentName BuildingNumber 1電子通信1 2コンピュータサイエンス2 3計測し、その結果、次のこのPROCを実行する上での技術4

--EXEC TestProc '<Parameters> 
--     <Param> 
--      <ColumnName>pkDepartmentId</ColumnName> 
--      <ColumnValue>1</ColumnValue>   
--     </Param> 
--     <Param> 
--      <ColumnName>DepartmentName</ColumnName> 
--      <ColumnValue>Electronics and Communication</ColumnValue>   
--     </Param> 
--     <Param> 
--      <ColumnName>BuildingNumber</ColumnName> 
--      <ColumnValue>1</ColumnValue>   
--     </Param>  
--    </Parameters>' 

CREATE PROCEDURE TestProc 
@parameters XML 
AS 
BEGIN 
    DECLARE @temp1 TABLE 
    (
      ColName VARCHAR(100) 
     , ColVal VARCHAR(4000)  
    ) 

    INSERT INTO @temp1 
    SELECT Params.Col.value('ColumnName[1]', 'VARCHAR(50)') ColName 
      , Params.Col.value('ColumnValue[1]', 'VARCHAR(50)') ColVal    FROM @parameters.nodes('//Parameters/Param') Params(Col) 

    DECLARE @sql VARCHAR(4000) 

    SET @sql = 'SELECT * FROM Departments WHERE ' 

    SELECT @sql = @sql + ColName + ' = ''' + ColVal + ''' AND ' 
    FROM @temp1 

    -- Trim last AND 
    SET @sql = SUBSTRING(@sql, 1, LEN(@sql) - 3) 

    PRINT @sql     

    EXEC (@sql)    

END 

は pkDepartmentId DepartmentName BuildingNumber 1つの電子通信1

を得ています
+0

XMLと 'DECLARE @ temp1 TABLE'テーブルに' ColumnType'が表示されませんか?また、 '@ sql'文字列をSQLインジェクションに対して脆弱にするように構築します。もしXMLから取り出す変数を' DECLARE'したいのであれば '@ sql'で使うことができます@sql = 'SELECT * FROM Departments WHERE id = @id AND firstName = @ firstName''のようなものを作成できますか? – rapt

+0

こんにちはRapt、私はColumnTypeを削除するコードを変更しました。変数を宣言してSQL文字列を作成する場合は、カーソルまたはwhileループを使用して@temp Tableのすべてのレコードをループする必要があります。 –

+0

ありがとう、とても助かりました! – rapt

0

デフォルトパラメータ:

create procedure MyPRoc1 
(
@param1 int, 
@param2 int =1 
) 
as 
begin 
    --code 
end 

あなたは、あなたの問題のためのXMLベースのアプローチを使用しようとすることができ

exec MyPRoc1 10 

または

exec MyPRoc1 1,1 
+0

私の場合ではありません - あなたはパラメータの数の上限を前提としているので、オプションのパラメータごとに特定のタイプを仮定しています。 – rapt

+0

パラメータの数については、必要に応じて新しいパラメータを簡単に追加することができます。デフォルトのオプションでは、プロセスを中断することはありません。可変型のパラメータに関しては、それらをすべてvarcharにして、プロシージャ内で必要に応じて処理する必要があります。私は推薦しますが、それは唯一のオプションです、SQLの "変数"データ型はありません – Diego

4

しないでください。すべてのデータベースのパフォーマンスを低下させようとしています。 T-SQLとコードの再利用は混在しません。

あなたはになりますか?これらのストアドプロシージャはすべて自動的に生成されます。これを行う多くのツールがあります。独自の方法を簡単に使用することができます.SQLを使用してテーブル定義をXMLに抽出し、XSLTを使用してこれをT-SQLに変換し、procを生成します。プロジェクトのビルドと連続した統合プロセスに自動化することができます。強力なタイプ、効率的なT-SQLコード、さらには機敏でDRY性の高い保守可能なプロセスにより、100種類のprocsを1回の変更で簡単に書き直すことができます。

+0

あなたはどのような再利用をしていますか? SQLクエリを動的に作成しますか? – rapt

1

テーブル値のパラメータTVP(SQL Serverのバージョンが> = 2008の場合)はどうですか?しかし、これは "未知の型"の部分を解決しません。私は...あなたがvarchar型(最大)、あるいはNVARCHAR(max)を使用し、必要に応じてそれをキャストしなければならないと思い

参照:SQL Serverの以前のバージョンのhttp://www.sommarskog.se/arrays-in-sql-2008.html

、以下を参照してください。