2017-11-30 4 views
-1

私はこれに多数の記事を見つけましたが、私は のいずれかを動作させることができませんでした。以下のコードは私が に来たのと最も近いです。私は下のddlSIPA listboxの値を読んで、 の結果は正しいように見えますが、SQL Serverはリストボックス項目の INステートメントを処理していないようです。複数のリストボックス項目(A、S、I、SIP、SIPAなどの文字など)をINを使用してパラメータ化されたSQLクエリに渡すにはどうすればよいですか?

public void LoadChecklist(Object sender, EventArgs e) 
{  
System.Data.DataTable SearchResultsTable = new System.Data.DataTable(); 
    SqlCommand cmd = new SqlCommand("sp_get_QUADRA_CHECKLIST", conn); 
    cmd.CommandType = CommandType.StoredProcedure; 
    //create sql adapter by passing command object 
    SqlDataAdapter adapter = new SqlDataAdapter(cmd); 

    SearchResultsTable.Clear(); 

    string strYourIDs = ""; 
    int[] yourSelectedIndexes = ddlSIPA.GetSelectedIndices(); 
    for (int i = yourSelectedIndexes.Length - 1; i >= 0; i--) 
    { 
     strYourIDs += "'" + ddlSIPA.Items[yourSelectedIndexes[i]].Value + "',"; 
    } 
    if (strYourIDs != "") 
     strYourIDs = strYourIDs.TrimEnd(",".ToCharArray()); 
    try 
    { 
     cmd.Parameters.AddWithValue("@SIPA", strYourIDs); 
     Response.Write(strYourIDs); 
     cmd.Parameters.AddWithValue("@AP_DEV", CbAPDev.Checked); 
     cmd.Parameters.AddWithValue("@PROD_DEV", cbProdDev.Checked); 
     cmd.Parameters.AddWithValue("@ROTYPE",         ddlROTYPE.SelectedItem.Value); 
     adapter.Fill(SearchResultsTable); 
     if (SearchResultsTable.Rows.Count > 0) 
     { 
      //SearchResultsTable.ToString(); 
      GV1.DataSource = SearchResultsTable; 
      GV1.DataBind(); 
     } 
     else if (SearchResultsTable.Rows.Count == 0) 
     { 
      //Response.Write("No records found!"); 
      ScriptManager.RegisterStartupScript(this, GetType(), "showalert", "alert('No records found!');", true); 
      GV1.DataBind(); 
     } 
    } 
    catch (System.Data.SqlClient.SqlException ex) 
    { 
     Response.Write(ex); 
    } 
    finally 
    { 
     conn.Close(); 
    } 
} 

SQLクエリ:

USE [VISIBILITY_BOARD] 
GO 


SET ANSI_NULLS ON 
GO 

SET QUOTED_IDENTIFIER OFF 
GO 



ALTER PROCEDURE [dbo].[sp_get_QUADRA_CHECKLIST] (
    @AP_DEV bit '' 
    ,@PROD_DEV bit = '' 
    ,@ROTYPE nvarchar(255) = '' 
    ,@SIPA nvarchar(255) = '') AS 
--,@RO nvarchar(255) = '') AS 


SELECT h.QUES_ANSWER 
, h.COMMENTS 
, cl.RO_TYPE 
, cl.RO 
, cl.QUES_ID 
, cl.DFQRO AS QDRO 
, cl.QUADRA_QUES 

FROM Tbl_QUADRA_CL cl 
LEFT JOIN TBL_QUADRA_ASSMNT_HIST h 
ON cl.QUES_ID = h.QUES_ID 
WHERE (cl.RO_TYPE = @ROTYPE OR @ROTYPE IS NULL) 
AND (cl.SIPA IN (@SIPA) OR @SIPA IS NULL) 
AND (cl.AP_DEV = @AP_DEV OR @AP_DEV IS NULL) 
AND (cl.PROD_DEV = @PROD_DEV or @PROD_DEV IS NULL) 
GROUP BY h.QUES_ANSWER 
, h.COMMENTS 
, cl.RO_TYPE 
, cl.RO 
, cl.QUES_ID 
, cl.DFQRO 
, cl.QUADRA_QUES 

SET QUOTED_IDENTIFIER On 
GO 
+0

に変更すると、そのようなリストを渡すことはできません。これにはテーブル値パラメータが最適です。そうしないと、動的SQLを使用することになります。また、あなたの手続きのために別の接頭辞を考慮する必要があります。 sp_接頭辞は予約されており、問題を引き起こす可能性があります。 http://sqlperformance.com/2012/10/t-sql-queries/sp_prefix –

+0

注意点としては、オプションのパラメータを含むすべてのクエリをキャッチするタイプのようです。これらのパラメータがnullになる唯一の方法は、フロントエンドからDBNullを渡す場合です。 –

+0

[varcharをカンマ区切りの値でSQL ServerのIN関数に渡す](https://stackoverflow.com/questions/878833/passing-a-varchar-full-com-comma-delimited-values-to)の可能な複製-a-sql-server-in-function) –

答えて

0

ここで問題です:AND (cl.SIPA IN (@SIPA) OR @SIPA IS NULL)

あなたは非常に一般的な間違いをしている - INオペレータはあなたがカンマで区切られた値のリストを想定したが、という単一の値にカンマで区切られたリストが含まれています。

を使用しているので、代わりにuse a table valued parameterにお知らせします。 - 間違いだ

  • クラスレベルSQLConnectionの使用:

    あなたのコード内のいくつかの他の問題もあるのでご注意ください。 SQLConnectionの正しい使用は、usingステートメント内のローカル変数となります。

  • IDisposableインターフェイスを実装し、廃棄しないクラスのインスタンスを使用する - SQLCommandおよびSQLDataAdapterを使用する場合。
  • AddWithValueを使用する - 詳細はCan we stop using AddWithValue() already?を参照してください。

より良いC#のコードをより次のようになります。あなたのストアドプロシージャのよう

public void LoadChecklist(Object sender, EventArgs e) 
{ 
    var SearchResultsTable = new DataTable(); 
    using (var con = new SqlConnection("<ConnectionStringGoesHere>")) 
    { 
     using (var cmd = new SqlCommand("sp_get_QUADRA_CHECKLIST", con)) 
     { 
      cmd.CommandType = CommandType.StoredProcedure; 
      using(var adapter = new SqlDataAdapter(cmd)) 
      { 
       using(var dtSIPA = new DataTable()) 
       { 
        dtSIPA.Columns.Add("Id", typeof(int)); -- assuming you are looking for a list of int values 
        int[] yourSelectedIndexes = ddlSIPA.GetSelectedIndices(); 
        for (int i = yourSelectedIndexes.Length - 1; i >= 0; i--) 
        { 
         dtSIPA.Rows.Add(ddlSIPA.Items[yourSelectedIndexes[i]].Value); 
        } 

        cmd.Parameters.Add("@AP_DEV", SqlDbType.Bit).Value = CbAPDev.Checked; 
        cmd.Parameters.Add("@PROD_DEV", SqlDbType.Bit).Value = cbProdDev.Checked; 
        cmd.Parameters.Add("@ROTYPE", SqlDbType.NVarChar, 255).Value = ddlROTYPE.SelectedItem.Value; 
        cmd.Parameters.Add("@SIPA", SqlDbType.Structured).Value = dtSIPA; 
       } 
       try 
       { 
        adapter.Fill(SearchResultsTable); 
       } 
       catch (System.Data.SqlClient.SqlException ex) 
       { 
        Response.Write(ex); 
       }      
      } 
     } 
    } 
} 

を、あなたは@SIPAパラメータにユーザー定義テーブル型を作成する必要があります。

CREATE TYPE SIPA AS TABLE 
(
    Id int 
) 

条件をAND (cl.SIPA IN (SELECT Id FROM @SIPA) OR (SELECT COUNT(*) FROM @SIPA) = 0)

+0

これで、HTMLリストボックスからSIPAの値を取得するのではなく、SIPAの値を保持するテーブルを作成する必要がありますか? –

+0

あなたはZoharですが、どうすればいいですか:ストアドプロシージャに関しては、@ SIPAのユーザ定義のテーブルタイプを作成する必要があります –

+0

create type文を使用します。基本を示すために私の答えを編集しました。 –

関連する問題