尝试忽略 Winforms 中的空文本框以过滤 sql 搜索查询
Posted
技术标签:
【中文标题】尝试忽略 Winforms 中的空文本框以过滤 sql 搜索查询【英文标题】:Trying to ignore null textboxes in Winforms to filter sql search query 【发布时间】:2021-07-21 21:08:41 【问题描述】:目前我正在尝试保留一个持久的 where 子句,然后通过附加是否存在每个文本框来附加额外的过滤器。问题是这给了我一个很好的命令,但是在尝试使用该命令时我仍然收到错误。如果有任何简化或指导,将不胜感激!
if (string.IsNullOrEmpty(make) && (string.IsNullOrEmpty(model)) && (string.IsNullOrEmpty(color)) && (string.IsNullOrEmpty(min)) && (string.IsNullOrEmpty(max)) && (string.IsNullOrEmpty(miles)))
SqlCommand updateDataGridViewCmd = new SqlCommand("select m.make, m.model, car.price, color.color, car.mileage, carlot.lotid, car.pic from car join makemodel as m ON m.mmid = car.mmid join color ON car.colorid = color.colorid join carlot ON carlot.carid = car.carid; ", sqlCon);
dt.Load(updateDataGridViewCmd.ExecuteReader());
dataGridView1.DataSource = dt;
else
StringBuilder sqlCommandText = new StringBuilder();
sqlCommandText.Append("select m.make, m.model, car.price, color.color, car.mileage, carlot.lotid, car.pic from car join makemodel as m ON m.mmid = car.mmid join color ON car.colorid = color.colorid join carlot ON carlot.carid = car.carid where");
string CommandText = sqlCommandText.ToString();
SqlCommand updateDataGridViewCmd = new SqlCommand(CommandText, sqlCon);
updateDataGridViewCmd.Parameters.AddWithValue("@make", make);
updateDataGridViewCmd.Parameters.AddWithValue("@model", model);
updateDataGridViewCmd.Parameters.AddWithValue("@min", min);
updateDataGridViewCmd.Parameters.AddWithValue("@max", max);
updateDataGridViewCmd.Parameters.AddWithValue("@mileage", miles);
updateDataGridViewCmd.Parameters.AddWithValue("@color", color);
if (!string.IsNullOrEmpty(make))
sqlCommandText.Append(" m.make = @make");
CommandText = sqlCommandText.ToString();
if (!string.IsNullOrEmpty(model))
sqlCommandText.Append(" OR m.model = @model");
CommandText = sqlCommandText.ToString();
if (!string.IsNullOrEmpty(min))
sqlCommandText.Append(" car.price between @min");
CommandText = sqlCommandText.ToString();
if (!string.IsNullOrEmpty(max))
sqlCommandText.Append(" AND @max");
CommandText = sqlCommandText.ToString();
else
sqlCommandText.Append(",");
CommandText = sqlCommandText.ToString();
if (!string.IsNullOrEmpty(color))
sqlCommandText.Append(" color.color = @color,");
CommandText = sqlCommandText.ToString();
if (!string.IsNullOrEmpty(miles))
sqlCommandText.Append(" car.price <= @mileage");
CommandText = sqlCommandText.ToString();
sqlCommandText.Append(";");
CommandText = sqlCommandText.ToString();
dt.Load(updateDataGridViewCmd.ExecuteReader());
dataGridView1.DataSource = dt;
错误:
【问题讨论】:
这里可以使用任何 ORM 吗?在处理动态查询时会有很大帮助 什么错误?请添加更多信息,否则只是一个猜谜游戏 可能是因为您没有使用and, or
之一链接条件
您生成的 SQL 存在大量语法错误。在调试器中看一下
命令是什么?
【参考方案1】:
您可能会看到一个错误,因为您没有使用and
或or
加入您的条件字符串。
如果这里没有 ORM 选项(这在组合查询时可能很实用),您可以使用 where 1=1
结束基本查询,然后使用 and x=...
或 or x=...
链接其他条件
在应用所有过滤器后,您也可以只设置一次CommandText = sqlCommandText.ToString();
【讨论】:
对品牌和型号进行了测试,得到了select m.make, m.model, car.price, color.color, car.mileage, carlot.lotid, car.pic from car join makemodel as m ON m.mmid = car.mmid join color ON car.colorid = color.colorid join carlot ON carlot.carid = car.carid where m.make = @make OR m.model = @model;
,它存储在命令文本中,这不是一个有效的查询吗?
我重新编辑以在命令文本中显示文本
WHERE 1=1
是不必要的。在List<string>
中捕获条件,然后将它们组合起来,例如string.Join(" OR ", myConditions)
@Eric 但他们并不都是and
或or
。它们混合在一起。使用字符串将它们全部连接起来。加入将导致值用相同的分隔符分隔
string.Join(" ", myConditions)
其中myConditions
包括and
/or
术语。混合使用或不使用括号来指定操作顺序在一般意义上是没有用的。【参考方案2】:
认为这是一个伪代码。我在这个编辑器中从头开始写了它。基本上,与其处理无穷无尽的条件,不如创建一个对象,将您的条件分组,然后对这些对象实例的输出进行分组。它应该为您构建一个完美的过滤器。
public class WhereToken
private List<SqlParameter> _localColl;
// privates declared here
privat bool _between;
public WhereToken (string col, object[] values, SqlDbType t, SqlParameterCollection paramColl)
// assign privates here
public WhereToken (string col, object value1, object value2, SqlDbType t, SqlParameterCollection paramColl)
// assign privates here
_between = true;
_values = new object[]value1, value2;
public string Write()
if (values.Length = 0)
return null;
_localColl = new List<SqlParameter>();
var b = new StringBuilder();
b.Append("(");
for (int i = 0; l < _values.Length; i++)
var pName = string.Concat("@", col, i);
var p = new SqlParameter(pName, values[i], _sqlType);
b.Append(_col);
if (_between)
b.Append(" BETWEEN ");
else
b.Append("=");
b.Append(pName);
if (i < values.Length - 1)
if (_between)
b.Append(" AND ");
else
b.Append(" OR ");
b.Append(")");
foreach(var pp in _localColl)
_paramColl.Parameters.Add(pp);
return b.ToString();
// In code
var tokens = new List<WhereToken>();
var wt1 = new WhereToken("make", new string[]txt.Make.Text, SqlDbType.NVarchar, sqlCommand.ParameterCollection);
tokens.Add(w1);
// in real life, you need to check if both values present, etc
var wt2 = new WhereToken("year", Convert.ToInt32(txt.YearMin.Text), Convert.ToInt32(txt.YearMax.Text), SqlDbType.Int, sqlCommand.ParameterCollection);
tokens.Add(w2);
// more items here . . . .
var builder = new StringBuilder(yourMainSQLSelect);
builder.Append(" WHERE 1=1"); // 1=1 what if the tokens don't generate
for (int i = 0; i < tokens.Length; i++)
string token = tokens[i].Write();
if (token == null) continue;
builder.Append(" AND ");
builder.Append(token);
sqlCommand.CommandText = builder.ToString();
这段代码 ^^ 应该为您构建类似的东西
... where 1=1 and make=@make0 and (year BETWEEN @year0 AND @year1)
当然,您可以改进有关如何从WhereToken
解析和输出的内置逻辑。但这是适合您的概念 - 解析小标记然后加入它们。不要尝试为所有输入字段构建逻辑
【讨论】:
【参考方案3】:在我看来,如果某些输入字符串为空或空,您想用谓词扩展 WHERE。
让我们忽略空字符串,所以我不必写:is null or empty string
SELECT ... FROM TABLECUSTOMERS WHERE <predicate1> OR <predicate2> OR ...
您添加的谓词取决于哪些输入字符串为空。在我看来,大多数时候,如果输入字符串为空,你想省略谓词。像这样的:
if (inputStringName != null)
strBuilder.Append("OR CustomerName = @Name")
这与:
OR (@Name != null AND @Name == CustomerName)
如果你想使用 AND 而不是 OR:
AND (@Name == null OR @Name == CustomerName)
所以我的建议是:创建一个包含所有可能变量的 SQL 命令,然后更改命令以使谓词也测试参数是否等于 null
SELECT ... FROM car
JOIN ...
WHERE ( NOT @Make = NULL AND @Make = m.Make)
OR ( NOT @Model = NULL AND @Model = m.Model)
OR ( NOT @Mileage = NULL AND @Mileage > car.Mileage)
因此,在使用参数之前,请检查参数是否为空。取决于您是要附加 AND 还是 OR 使用类似:
或(不是@Value = NULL AND @Value = car.MyValue) AND(@Value = NULL 或 @Value = car.MyValue)我的SQL有点生疏,一直在用实体框架,所以对NOT =
有点不确定,可能这个应该是!=
,可能括号应该多一些,不过我猜你明白要点。
为了避免必须检查空字符串:在您之前将空字符串设为空AddWithValue
【讨论】:
以上是关于尝试忽略 Winforms 中的空文本框以过滤 sql 搜索查询的主要内容,如果未能解决你的问题,请参考以下文章
Linux/bash 解析文本输出,选择字段,仅忽略一个字段中的空值