MS SQL — параметризованный запрос с динамическим количеством параметров

Прямо сейчас я использую следующий код для создания предложения WHERE в моем запросе. У меня есть параметр для столбца поиска (searchColumn) плюс еще один параметр из проверенного списка, который я использую.

Если ни один элемент не отмечен, предложение WHERE вообще отсутствует.

Можно ли поместить это в параметризованный запрос? Для второй части, скорее всего, есть такой способ, как searchColumn NOT IN ( ... ), где ... ist данные из массива. Хотя я не уверен, как поступить в случае, когда вообще ничего не проверяется.

Любые мысли или ссылки по этому поводу?

strWhereClause = "";
foreach (object objSelected in clbxFilter.CheckedItems)
{
     string strSearch = clbxFilter.GetItemText(objSelected);

     if (strWhereClause.Length == 0)
     {
         strWhereClause += "WHERE (" + searchColumn + " = '" + strSearch + "' "
         + "OR " + searchColumn + " = '" + strSearch + "') ";
     }
     else
     {
     strWhereClause += "OR (" searchColumn " = '" + strSearch + "' "
                                           + "OR " + searchColumn + " = '" + strSearch + "') ";
     }
}

person Fuzzzzel    schedule 09.04.2015    source источник
comment
Эта статья Гейл Шоу является отличный ресурс. В нем обсуждается построение строк запроса в tsql. Несмотря на то, что вы строите строку запроса в коде .Net, в статье все еще есть много актуальной информации.   -  person Dave Mason    schedule 09.04.2015
comment
Спасибо, это очень полезно!   -  person Fuzzzzel    schedule 09.04.2015
comment
Вы можете рассмотреть возможность использования табличного параметра и выполнения `OR + searchColumn + IN (SELECT [value] FROM ' + tvpName + ).   -  person Jodrell    schedule 09.04.2015


Ответы (2)


Похоже, вы просто пытаетесь динамически построить параметризованную строку запроса с помощью С#. Вы на полпути со своим кодом — мой пример ниже создает словарь с именами параметров и значениями параметров, который затем можно использовать для создания SqlParamter. Одна вещь, в которой я не уверен на 100%, это то, откуда берется searchColumn - это сгенерировано из пользовательского ввода? Это может быть опасно, а параметризация потребует использования некоторого динамического SQL и, возможно, некоторой проверки с вашей стороны.

strWhereClause = "";
Dictionary<string, string> sqlParams = new Dictionary<string, string>();
int i = 1;
string paramName= "@p" + i.ToString(); // first iteration: "@p1"
foreach (object objSelected in clbxFilter.CheckedItems)
{
     string strSearch = clbxFilter.GetItemText(objSelected);

     if (strWhereClause.Length == 0)
     {
         strWhereClause += "WHERE (thisyear." + strKB + " = @p1 OR " + searchColumn + " = @p1) ";
         sqlParams.Add(paramName, strSearch);
         i = 2;
     }
     else
     {
         paramName = "@p" + i.ToString(); // "@p2", "@p3", etc.
         strWhereClause += "OR (" searchColumn " = " + paramName + " "OR " + searchColumn + " = " + paramName + ") ";
        sqlParams.Add(paramName, strSearch);
        i++;
     }
}

Затем, при параметризации вашего запроса, просто переберите свой словарь.

if (sqlParams.Count != 0 && strWhereclause.Length != 0)
{
  foreach(KeyValuePair<string, string> kvp in sqlParams)
  {
    command.Parameters.Add(new SqlParamter(kvp.Name, SqlDbType.VarChar) { Value = kvp.Value; });
  }
}
person Dan Field    schedule 09.04.2015
comment
Большое спасибо! Это делает свое дело. SearchColumn передается программно и различает два столбца, которые могут содержать одинаковые значения, поэтому это не будет утечкой безопасности. - person Fuzzzzel; 09.04.2015

Только для справки:

    string strWhereClause;
    string searchColumn;
    string strKB;
    SqlCommand cmd = new SqlCommand();
    private void button1_Click(object sender, EventArgs e)
    {
        strWhereClause = "";
        int ParmCount = 0;         
        foreach (object objSelected in clbxFilter.CheckedItems)
        {
            string strSearch = clbxFilter.GetItemText(objSelected);
            ParmCount += 1;
            string strParamName = "@Param" + ParmCount.ToString(); //Param1→ParamN
            cmd.Parameters.Add(strParamName, SqlDbType.NVarChar);
            cmd.Parameters[strParamName].Value = strSearch;
            if (strWhereClause.Length == 0)
            {
                strWhereClause += "WHERE (thisyear." + strKB + " = " + strParamName + " "
                               + "OR " + searchColumn + " = " + strParamName + ") ";
            }
            else
            {
                strWhereClause += "OR (thisyear." + strKB + " = " + strParamName + " "
                               + "OR " + searchColumn + " = " + strParamName + ") ";
            }
        }
    }
person Angus Chung    schedule 09.04.2015