web-dev-qa-db-ja.com

リストをストアドプロシージャのパラメーターとして渡すにはどうすればよいですか?

リスト名を返すユーザーIDのリストを渡すことを探しています。出力された名前(COALESCEなど)を処理する計画がありますが、ユーザーIDのリストを渡す最適な方法を見つけようとしています。私のsprocの根性は次のようになります。

create procedure [dbo].[get_user_names]
@user_id_list, --which would equal a list of incoming ID numbers like (5,44,72,81,126)
@username varchar (30) output
as
select last_name+', '+first_name 
from user_mstr
where user_id in @user_id_list

ここで、@ user_id_listの値を渡すことが主な関心事です。

27
shaner4011

SQL Serverのストアドプロシージャに値の配列を渡すための推奨される方法は、テーブル値パラメーターを使用することです。

まず、次のようにタイプを定義します。

CREATE TYPE UserList AS TABLE ( UserID INT );

次に、その型をストアドプロシージャで使用します。

create procedure [dbo].[get_user_names]
@user_id_list UserList READONLY,
@username varchar (30) output
as
select last_name+', '+first_name 
from user_mstr
where user_id in (SELECT UserID FROM @user_id_list)

そのため、そのストアドプロシージャを呼び出す前に、テーブル変数を入力します。

DECLARE @UL UserList;
INSERT @UL VALUES (5),(44),(72),(81),(126)

そして最後にSPを呼び出します。

EXEC dbo.get_user_names @UL, @username OUTPUT;
36
Matthew Sontum

私が知る限り、3つの主要な候補があります。テーブル値パラメーター、区切りリスト文字列、JSON文字列です。

2016年以降、区切り記号付きルートが必要な場合は、組み込みのSTRING_SPLITを使用できます。 https://docs.Microsoft.com/en-us/sql/t-sql/functions/string-split-transact- sql

それはおそらく最も簡単で、最も簡単で簡単なアプローチでしょう。

また、2016年以降、JSONはnvarcharとして渡され、OPENJSONで使用できます。 https://docs.Microsoft.com/en-us/sql/t-sql/functions/openjson-transact-sql

スキーマ内で大幅に変化する可能性のある、より構造化されたデータセットを渡す場合は、おそらく最適です。

TVPは、より構造化されたパラメータを渡すための標準的な方法であるように思われますが、その構造、明示性、および基本的な値/型チェックが必要な場合はまだ有効です。ただし、消費者側では少し面倒です。 2016+をお持ちでない場合、これがおそらくデフォルト/最適なオプションです。

これらの具体的な考慮事項のいずれかと、パラメーターの構造を明示することの好みとの間のトレードオフだと思います。つまり、2016 +を使用している場合でも、パラメーターのタイプ/スキーマを明示するよりも、文字列を渡して、何らかの方法で解析します。

13
Ambrose Little

この問題を次の方法で解決しました。

  1. C#では、文字列変数を作成しました。

string userId = "";

  1. リストの項目をこの変数に入れます。 「、」を区切りました。

例:C#で

userId= "5,44,72,81,126";

sQL Serverに送信

 SqlParameter param = cmd.Parameters.AddWithValue("@user_id_list",userId);
  1. 受信したリスト(タイプがNVARCHAR(Max)である)をテーブルに変換するために、SQLサーバーに分離関数を作成します。
CREATE FUNCTION dbo.SplitInts  
(  
   @List      VARCHAR(MAX),  
   @Delimiter VARCHAR(255)  
)  
RETURNS TABLE  
AS  
  RETURN ( SELECT Item = CONVERT(INT, Item) FROM  
      ( SELECT Item = x.i.value('(./text())[1]', 'varchar(max)')  
        FROM ( SELECT [XML] = CONVERT(XML, '<i>'  
        + REPLACE(@List, @Delimiter, '</i><i>') + '</i>').query('.')  
          ) AS a CROSS APPLY [XML].nodes('i') AS x(i) ) AS y  
      WHERE Item IS NOT NULL  
  );
  1. メインのストアプロシージャで、以下のコマンドを使用して、エントリリストを使用します。

SELECT user_id = Item FROM dbo.SplitInts(@user_id_list、 '、');

5
BehrouzMoslem

Azure DB、Azure Data WH、およびSQL Server 2016から、STRING_SPLITを使用して、@ sparrowで記述されたものと同様の結果を得ることができます。

@sparrowからのコードのリサイクル

where user_id in (Select value from STRING_SPLIT( @user_id_list, ',')

ストアドプロシージャに値のリストを受け入れる簡単で効果的な方法

3
Peter Henry

これを試すことができます:

create procedure [dbo].[get_user_names]
    @user_id_list varchar(2000), -- You can use any max length

    @username varchar (30) output
    as
    select last_name+', '+first_name 
    from user_mstr
    where user_id in (Select ID from dbo.SplitString( @user_id_list, ',') )

次に、SplitStringのユーザー定義関数を示します。

Create FUNCTION [dbo].[SplitString]
(    
      @Input NVARCHAR(MAX),
      @Character CHAR(1)
)
RETURNS @Output TABLE (
      Item NVARCHAR(1000)
)
AS
BEGIN
      DECLARE @StartIndex INT, @EndIndex INT

      SET @StartIndex = 1
      IF SUBSTRING(@Input, LEN(@Input) - 1, LEN(@Input)) <> @Character
      BEGIN
            SET @Input = @Input + @Character
      END

      WHILE CHARINDEX(@Character, @Input) > 0
      BEGIN
            SET @EndIndex = CHARINDEX(@Character, @Input)

            INSERT INTO @Output(Item)
            SELECT SUBSTRING(@Input, @StartIndex, @EndIndex - 1)

            SET @Input = SUBSTRING(@Input, @EndIndex + 1, LEN(@Input))
      END

      RETURN
END
1
Sparrow

この単純な「インライン」メソッドを使用して、string_list_typeパラメーターを作成できます(SQL Server 2014で機能します)。

declare @p1 dbo.string_list_type
insert into @p1 values(N'myFirstString')
insert into @p1 values(N'mySecondString')

ストアドプロシージャを実行するときの使用例:

exec MyStoredProc @MyParam=@p1
0
Chris Halcrow

使用できるかもしれません:

select last_name+', '+first_name 
from user_mstr
where ',' + @user_id_list + ',' like '%,' + convert(nvarchar, user_id) + ',%'
0
Skippy