2

重複の可能性:
コンマで送信されたパラメーターを使用したSQL検索クエリのヘルプ

テーブルに対してselectを実行し、タイプが1つの入力変数を必要とするストアドプロシージャを作成したいと思いますvarchar(max)

,入力パラメータとしてで区切られた一連の値を送信したいのですが、たとえば

'Jack','Jane','Joe'

次に、これらの名前の1つを含む行を取得します。

SQLでは、コードは次のようになります

Select * from Personnel where Name in ('Jack','Joe','Jane');  

ここで、C#アプリに変数を設定し、strNamesと言って、次のように入力します。

string strNames = "'Jack','Joe','Jane'";

この変数をSPに送信して実行します。何かのようなもの

Select * from Personnel where Name in (''Jack','Joe','Jane'') -- this is wrong

しかし、SQL Serverにそのようなコマンドを実行するように指示するにはどうすればよいですか?

私はこれを実現する必要があり、それが可能であることを知っています。手がかりを教えてください。

4

4 に答える 4

10

まず、ストアドプロシージャに渡すときに、単一の名前を引用符で囲む必要はありません。

using (SqlCommand cmd = new SqlCommand("MyStoredProc", conn))
{
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.AddWithValue("@longFilter", "Jack,Jill,Joe");

    using (SqlDataReader reader = cmd.ExecuteReader())
    {
        ...
    }
}

次に、ストアドプロシージャで、次のように単純なテキスト関数と一時テーブルを使用して、文字列をコンマで分割し、文字列の各部分の一時テーブルへのエントリを作成できます。

DECLARE @temp AS TABLE (Name NVARCHAR(255))

IF ISNULL(@longFilter, '') <> ''
BEGIN
    DECLARE @s NVARCHAR(max)
    WHILE LEN(@longFilter) > 0
    BEGIN
        IF CHARINDEX(',', @longFilter) > 0
        BEGIN
            SET @s = LTRIM(RTRIM(SUBSTRING(@longFilter, 1, CHARINDEX(',', @longFilter) - 1)))
            SET @longFilter = SUBSTRING(@longFilter, CHARINDEX(',', @longFilter) + 1, LEN(@longFilter))
        END ELSE
        BEGIN
            SET @s = LTRIM(RTRIM(@longFilter))
            SET @longFilter= ''
        END

        -- This was missing until 20140522
        INSERT INTO @temp (Name) VALUES (@s)
    END
END

後で以下SELECTを使用して、名前が含まれているすべての人のリスト、または行が含まれていない@temp場合はすべての人のリストを取得し@tempます(フィルタリングされていない結果)。

SELECT * FROM Personnel WHERE Name IN (SELECT Name FROM @temp) OR (SELECT COUNT(*) FROM @temp) = 0
于 2013-01-10T12:02:09.283 に答える
5

テーブル値パラメータを使用できます。

基本的に、プロシージャのパラメータとして値のリストを挿入し、それらをテーブルとして使用することができます。

Select * from Personnel 
  where Name in (select name from @NamesTable).

さて、詳細

  • テーブル値パラメーターを使用するには、パラメーターのタイプをSQLServerで事前定義する必要があります。

    create type NamesTable as table (Name varchar(50))
    
  • 次に、定義されたタイプをプロシージャのパラメータとして使用できます。

    create procedure getPersonnelList
      @NamesTable NamesTable readonly
    as
    begin
      select * from personnel
        where Name in (select Name from @NamesTable)
    end
    

    このSQLFiddleで、実際に動作していることがわかります。

  • C#側では、パラメーターを作成する必要があります。コレクションに名前があり、文字列を作成する場合は、それを使用してパラメーターを生成できます。コンマ区切りの文字列の場合は、クイックstring.Splitで処理できます。私はあなたの詳細を知らないので、私はあなたがList<string>呼ばれたと仮定しますnames。次のようなものを使用して、プロシージャに送信するテーブル値パラメータに変換する必要があります。

    DataTable tvparameter = new DataTable();
    tvparameter.Columns.Add("Name", typeof(string));
    foreach (string name in names)
    {
      tvparameter.Rows.Add(name);
    }
    

    TVPをC#コードで生成する方法の詳細については、SOの質問を参照してください。

  • これで、そのパラメーターをプロシージャーに送信する必要があります。それだけです。これは、プロシージャを実行して結果を出力する完全なコンソールプログラムです。

    List<string> names = new List<string> { "Joe", "Jane", "Jack" };
    
    using (SqlConnection cnn = new SqlConnection("..."))
    {
      cnn.Open();
      using (SqlCommand cmd = new SqlCommand("getPersonnelList", cnn))
      {
        cmd.CommandType = CommandType.StoredProcedure;
    
        DataTable tvparameter = new DataTable();
        tvparameter.Columns.Add("Name", typeof(string));
        foreach (string name in names)
        {
          tvparameter.Rows.Add(name);
        }
    
        cmd.Parameters.AddWithValue("@NamesTable", tvparameter);
    
        using (SqlDataReader dr = cmd.ExecuteReader())
        {
          while (dr.Read())
          {
            Console.WriteLine("{0} - {1}", dr["ID"], dr["Name"]);
          }
        }
      }
    }
    
于 2013-01-10T13:07:15.043 に答える
2

カンマ区切りの文字列をテーブルに分割するには、SQLServerの分割関数が必要だと思います。これらのリンクを参照してください。

SQL Serverの関数を分割して、カンマ区切りの文字列をテーブルに分割します

区切り文字列を解析するSQLユーザー定義関数

次を使用してテーブルからデータを選択できます

Select * from 
Personnel where 
  Name in (select items from dbo.Split ('Jack,Joe,Jane',','))
于 2013-01-10T11:57:35.890 に答える
2

Nameが文字列に含まれているかどうかを簡単に確認できます。フルネームと一致するように、末尾の先頭のコンマに注意してください

string strNames = ",Jack,Joe,Jane,";

SQLは次のようになります

select * from Personnel where PATINDEX('%,' + Name + ',%', @strNames) > 0

http://www.sqlfiddle.com/#!3/8ee5a/1を参照してください

于 2013-01-10T12:04:16.503 に答える