リスト名を返すユーザー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の値を渡すことが主な関心事です。
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;
私が知る限り、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 +を使用している場合でも、パラメーターのタイプ/スキーマを明示するよりも、文字列を渡して、何らかの方法で解析します。
この問題を次の方法で解決しました。
string userId = "";
例:C#で
userId= "5,44,72,81,126";
sQL Serverに送信
SqlParameter param = cmd.Parameters.AddWithValue("@user_id_list",userId);
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 );
SELECT user_id = Item FROM dbo.SplitInts(@user_id_list、 '、');
Azure DB、Azure Data WH、およびSQL Server 2016から、STRING_SPLITを使用して、@ sparrowで記述されたものと同様の結果を得ることができます。
@sparrowからのコードのリサイクル
where user_id in (Select value from STRING_SPLIT( @user_id_list, ',')
ストアドプロシージャに値のリストを受け入れる簡単で効果的な方法
これを試すことができます:
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
この単純な「インライン」メソッドを使用して、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
使用できるかもしれません:
select last_name+', '+first_name
from user_mstr
where ',' + @user_id_list + ',' like '%,' + convert(nvarchar, user_id) + ',%'