如何基于多条件搜索数据集并支持空控件查询
实现多条件动态搜索(支持空控件自动忽略)
需求说明
需要实现多条件查询数据集,当TextBox、ComboBox等控件为空时,该条件自动跳过,不参与查询逻辑,示例场景:
- 仅按日期范围+公司名查询:
check_date BETWEEN date1 AND date2 AND check_corporate = 'xxx' - 仅按分组+搜索关键词查询:
check_group = 'xxx' AND (check_name LIKE '%xxx%' OR check_num LIKE '%xxx%')
现有代码问题
当前searchReports方法硬拼接所有SQL条件,当控件为空时会生成check_corporate = ''这类无效条件,导致查询结果不符合预期;同时直接拼接用户输入存在SQL注入风险。
改进方案(动态构建SQL+参数化查询)
通过动态添加条件的方式,仅当控件有值时才将对应条件加入SQL语句,同时使用参数化查询避免注入问题:
Sub searchReports() ' 基础SQL语句,1=1用于方便后续拼接AND条件 Dim sqlBuilder As New StringBuilder("SELECT * FROM tblchecklist WHERE 1=1") Dim cmdParams As New List(Of MySql.Data.MySqlClient.MySqlParameter)() ' 处理日期范围条件:仅当两个日期控件都有有效输入时添加 If dateFrom.Value <> DateTime.MinValue AndAlso dateTo.Value <> DateTime.MinValue Then sqlBuilder.Append(" AND check_date BETWEEN @date1 AND @date2") cmdParams.Add(New MySql.Data.MySqlClient.MySqlParameter("@date1", dateFrom.Value.ToString("yyyy-MM-dd"))) cmdParams.Add(New MySql.Data.MySqlClient.MySqlParameter("@date2", dateTo.Value.ToString("yyyy-MM-dd"))) End If ' 处理公司下拉框条件:仅当控件非空时添加 If Not String.IsNullOrEmpty(combo_corpReports.Text.Trim()) Then sqlBuilder.Append(" AND check_corporate = @corp") cmdParams.Add(New MySql.Data.MySqlClient.MySqlParameter("@corp", combo_corpReports.Text.Trim())) End If ' 处理分组下拉框条件:仅当控件非空时添加 If Not String.IsNullOrEmpty(combo_groupReports.Text.Trim()) Then sqlBuilder.Append(" AND check_group = @group") cmdParams.Add(New MySql.Data.MySqlClient.MySqlParameter("@group", combo_groupReports.Text.Trim())) End If ' 处理搜索框条件:匹配名称或编号,仅当输入非空时添加 Dim searchText As String = txt_searchReports.Text.Trim() If Not String.IsNullOrEmpty(searchText) Then sqlBuilder.Append(" AND (check_name LIKE @search OR check_num LIKE @search)") cmdParams.Add(New MySql.Data.MySqlClient.MySqlParameter("@search", $"%{searchText}%")) End If ' 添加统一排序规则 sqlBuilder.Append(" ORDER BY check_date ASC") ' 执行查询,Using语句自动释放资源 Using da As New MySql.Data.MySqlClient.MySqlDataAdapter(sqlBuilder.ToString(), conn) da.SelectCommand.Parameters.AddRange(cmdParams.ToArray()) Dim ds As New DataSet() da.Fill(ds, "tblchecklist") dgv_reports.DataSource = ds.Tables("tblchecklist") End Using End Sub Private Sub txt_searchReports_TextChanged(sender As Object, e As EventArgs) Handles txt_searchReports.TextChanged searchReports() End Sub ' 优化loadReports方法,复用统一搜索逻辑 Sub loadReports() ' 清空所有搜索控件 combo_groupReports.Text = "" combo_corpReports.Text = "" txt_searchReports.Text = "" dateFrom.Value = DateTime.MinValue dateTo.Value = DateTime.MinValue ' 调用搜索方法加载全量数据 searchReports() End Sub
关键说明
WHERE 1=1是动态条件拼接的常用技巧,无需判断是否为第一个条件,直接追加AND xxx即可- 每个条件仅在控件有有效值时才加入SQL,空控件对应的条件自动忽略,完全匹配需求
- 参数化查询替代字符串拼接,彻底杜绝SQL注入风险
- 使用
StringBuilder构建SQL比多次字符串拼接更高效 Using语句自动释放MySqlDataAdapter资源,避免内存泄漏
内容的提问来源于stack exchange,提问作者Nnek Lecxe
相关产品推荐
相关产品推荐

