はい、テーブル値パラメーターを使用します。最初に型を作成します:
CREATE TYPE dbo.StudentIDs(ID INT PRIMARY KEY);
プレ>これで、プロシージャでこれを使用できるようになりました (ネストされた
IN
を変更したことに注意してください) 適切な結合へのクエリ):CREATE PROCEDURE dbo.MarkStudentsAsDeleted @IDs dbo.StudentIDs READONLY AS BEGIN SET NOCOUNT ON; UPDATE s SET IsDeleted = 1 FROM dbo.Students AS s INNER JOIN dbo.Class AS c ON s.StudentId = c.StudentId INNER JOIN dbo.ClassValueTable AS ct ON c.PassId = ct.Id WHERE ct.IsDeleted <> 1 AND EXISTS (SELECT 1 FROM @IDs WHERE StudentID = s.StudentID); END GO
プレ>C# コードは DataTable を渡すか、コンマ区切りのリストではなく、activeIds のコレクションを組み立てます。
DataTable dt = new DataTable(); dt.Columns.Add("ID", typeof(int)); dt.Rows.Add(1); dt.Rows.Add(2); dt.Rows.Add(3); dt.Rows.Add(4); ... open connection etc. ... SqlCommand cmd = new SqlCommand("dbo.MarkStudentsAsDeleted", conn); cmd.CommandType = CommandType.StoredProcedure; SqlParameter tvp1 = cmd.Parameters.AddWithValue("@IDs", dt); tvp1.SqlDbType = SqlDbType.Structured; cmd.ExecuteNonQuery(); ... close, dispose, etc. ...
プレ>ストアド プロシージャに必ず文字列を渡したい場合は、分割関数を使用する必要があります。例:
CREATE FUNCTION dbo.SplitInts ( @List VARCHAR(MAX), @Delimiter VARCHAR(255) = ',' ) RETURNS TABLE WITH SCHEMABINDING AS RETURN ( SELECT [value] = y.i.value('(./text())[1]', 'int') FROM ( SELECT x = CONVERT(XML, '<i>' + REPLACE(@List, @Delimiter, '</i><i>') + '</i>').query('.') ) AS a CROSS APPLY x.nodes('i') AS y(i) ); GO
プレ>ストアド プロシージャは次のようになります。
CREATE PROCEDURE dbo.MarkStudentsAsDeleted @IDs VARCHAR(MAX) AS BEGIN SET NOCOUNT ON; UPDATE s SET IsDeleted = 1 FROM dbo.Students AS s INNER JOIN dbo.Class AS c ON s.StudentId = c.StudentId INNER JOIN dbo.ClassValueTable AS ct ON c.PassId = ct.Id WHERE ct.IsDeleted <> 1 AND EXISTS (SELECT 1 FROM dbo.SplitInts(@IDs, ',') WHERE Item = s.StudentID); END GO
プレ>