SQL Query的Trickly null验证

时间:2014-06-25 08:50:59

标签: c# sql-server dbnull

"AND TT.[_TYPE] = CASE WHEN " + String.IsNullOrEmpty(lstTypeSearch.SelectedItem) ? 
 DBNull.Value} +  
" IS NULL THEN TT.[_TYPE] ELSE " + lstTypeSearch.SelectedItem + " END ";

以上是我查询的伪方面。

我需要对null的listbox项进行验证,然后设置为DBNull.Value,它将在SQL Query中传递给CASE WHEN。

有没有更好的方法来实现这一目标?我收到大量的String to Bool,Null to String转换错误...

此外,有没有将DBNull.Value作为参数传递到数据访问层?

编辑:原始查询属于静态类。

    public static readonly string SqlGetItemsBy_Number_Capacity_Type =   
    "SELECT TT.[_NUMBER], " +
    "TT.[CAPACITY], " +
    "TT.[_TYPE], " +                  
    "TS.[SESSIONE] " +
    "FROM [ITEMS] AS TT, //some code
    "WHERE //some code
    "AND TT.[_TYPE] = CASE WHEN @Type IS NULL THEN TT.[_TYPE] ELSE @Type END";

如果我在SQL Server中运行相同的查询,它可以正常工作。

  SELECT //some code
  AND [_TYPE] = CASE WHEN NULL IS NULL THEN [_TYPE] ELSE @TYPE END

最后:我决定使用SQL Append并跟随验证/设置参数。

    string paramAppend;
    var bld = lstTypeSearch.SelectedItem;

    if (bld != null)
    {
        paramAppend = "AND TT.[_TYPE] = " + lstTypeSearch.SelectedItem.ToString();
    }
    else
        paramAppend = "";

4 个答案:

答案 0 :(得分:3)

看起来lstTypeSearch这里代表一个列名(因此参数化:不是一个选项),所以我要说的第一件事是:确保你列出白名单。而不是试图一气呵成,将两种情况分开:

if(string.IsNullOrEmpty(lstTypeSearch.SelectedItem))
{
    // nothing to check?
}
else
{
    CheckValidColumn(lstTypeSearch.SelectedItem); // throws if white-list fails
    sql.Append(" AND TT.[_TYPE] = [") // should probably add table alias
       .Append(lstTypeSearch.SelectedItem)
       .Append("]");
}    

如果我误解了,这不是一个列,那么只需参数化:

if(string.IsNullOrEmpty(lstTypeSearch.SelectedItem))
{
    // no restriction?
}
else
{
    sql.Append(" AND TT.[_TYPE] = @type");
    cmd.Parameters.AddWithValue("type", lstTypeSearch.SelectedItem);
}
// ...
cmd.CommandText = sql.ToString();

答案 1 :(得分:2)

首先,您应该使用参数,除非希望暴露于潜在的SQL注入威胁。

其次,如果要在代码中动态构建sql,更好的方法是仅在lstTypeSearch.SelectedItem不是空字符串或null时才添加sql条件。类似的东西:

sSql = "your sql query";
if(!String.IsNullOrEmpty(lstTypeSearch.SelectedItem)) {
    sSql += "TT.[_TYPE] = '" + lstTypeSearch.SelectedItem + "'";
}
sSql += ";"

btw,如果SelectedItem有一个只包含空格的字符串怎么办?考虑将String.IsNullOrEmpty替换为String.IsNullOrWhiteSpace。

答案 2 :(得分:2)

  

如果为null,则在SQL中将其提供给案例,因此它将返回所有数据。

我解释这意味着如果没有指定值,则返回所有行,否则按该值过滤。

我假设lstTypeSearch.SelectedItem是您的价值而且它是string。如果没有,则抛出或挖出字符串值。

command.CommandText =
    "SELECT * FROM TT WHERE @SelectedItem IS NULL OR TT.[_TYPE] = @SelectedItem";

var selectedItem = (string) lstTypeSearch.SelectedItem;

command.Parameters.AddWithValue("@SelectedItem",
    String.IsNullOrEmpty(selectedItem) ? (object) DBNull.Value : selectedItem);

using (var dataReader = command.ExecuteReader())
{
    ...
}

答案 3 :(得分:2)

通过编辑,您应该能够用:

替换最后一行
AND (@Type IS NULL OR TT.[_TYPE] = @Type)

更清楚,虽然坦率地说它不能用于优秀的查询缓存计划使用或优化; IMO最好只是编写正确的SQL。

至于传递价值:

object value = string.IsNullOrEmpty(lstTypeSearch.SelectedItem)
       ? (object)DBNull.Value : (object)lstTypeSearch.SelectedItem;
// ...
cmd.Parameters.AddWithValue("Type", value);