1

2つの列を保持するテーブルDEPTがあります- ID, NAME

検索フォームにはDEPTテーブルのIDが表示され、ユーザーは任意の数のIDを選択してフォームを送信し、関連するを取得できNAMEsます。

明確化/入力:

  • 動的クエリを作成したくありません-管理できません。
  • テーブル値パラメーターを使用したスト​​アドプロシージャが好きです

続行する他の解決策はありますか?

注:
この例は1つのテーブルで単純です。実際には、6つ以上のテーブルを処理する必要があります。

提案をありがとう

4

1 に答える 1

8
CREATE TYPE dbo.DeptList
AS TABLE
(
  ID INT
);
GO

CREATE PROCEDURE dbo.RetrieveDepartments
  @dept_list AS dbo.DeptList READONLY
AS
BEGIN
  SET NOCOUNT ON;

  SELECT Name FROM dbo.table1 WHERE ID IN (SELECT ID FROM @dept)
  UNION ALL 
  SELECT Name FROM dbo.table2 WHERE ID IN (SELECT ID FROM @dept)
  -- ...
END
GO

C# コードで、DataTable を作成し、ID を入力して、ストアド プロシージャに渡します。tempList というリストが既にあり、ID が id に格納されていると仮定します。

DataTable tvp = new DataTable();
tvp.Columns.Add(new DataColumn("ID"));

foreach(var item in tempList)
{ 
    tvp.Rows.Add(item.id); 
}

using (connObject)
{
    SqlCommand cmd = new SqlCommand("StoredProcedure", connObject);
    cmd.CommandType = CommandType.StoredProcedure;
    SqlParameter tvparam = cmd.Parameters.AddWithValue("@dept_list", tvp);
    tvparam.SqlDbType = SqlDbType.Structured;
    ...
}

分割機能も使えます。たくさんありますが、入力が安全であることを保証できる場合 (<、>、& などはありません)、これが気に入っています。

CREATE FUNCTION dbo.SplitInts_XML
(
   @List       VARCHAR(MAX),
   @Delimiter  CHAR(1)
)
RETURNS TABLE
AS
   RETURN 
   (  
      SELECT Item = 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.RetrieveDepartments
  @dept_list VARCHAR(MAX)
AS
BEGIN
  SET NOCOUNT ON;

  ;WITH d AS (SELECT ID = Item FROM dbo.SplitInts(@dept_list, ','))
  SELECT Name FROM dbo.table1 WHERE ID IN (SELECT ID FROM d)
  UNION ALL
  SELECT Name FROM dbo.table2 WHERE ID IN (SELECT ID FROM d)
  -- ...
END
GO
于 2012-05-24T20:21:52.363 に答える