如何去除MySQL参数化查询中输入的%通配符作用?
解决MySQL参数化查询中用户输入通配符的问题
嘿,我明白你的困扰——你已经在用参数化查询防注入了,但用户输入的%还是会触发LIKE的通配符功能,这确实不符合预期。其实问题出在两个地方:一是你在参数里额外加了%(和SQL语句里的concat重复了),二是没有转义用户输入里的通配符字符。
核心思路
MySQL的LIKE语句里,%和_是通配符,参数化查询只会帮你防止SQL注入,但不会自动转义这些通配符。所以我们需要:
- 先转义用户输入中的通配符,把
%替换成\%,_替换成\_(MySQL用反斜杠作为转义符) - 去掉参数里多余的
%,因为SQL语句里已经通过concat添加了前后的通配符(如果你想要的是包含匹配的话)
调整后的代码示例
首先处理用户输入:
// 转义用户输入中的通配符,避免被当成LIKE的匹配符号 string searchInput = sc.sc_SearchBox.Text .Replace("%", @"\%") .Replace("_", @"\_");
然后修改数据库查询部分:
// SQL语句保持concat的逻辑,但参数不再额外拼接% MySqlCommand command = new MySqlCommand("SELECT * FROM singlecustomer WHERE name LIKE CONCAT('%', @search, '%') OR code LIKE CONCAT('%', @search, '%') OR id LIKE CONCAT('%', @search, '%')", con); // 传入转义后的纯用户输入,不加额外通配符 command.Parameters.Add(new MySqlParameter("@search", searchInput)); MySqlDataAdapter adapter = new MySqlDataAdapter(); adapter.SelectCommand = command; DataTable dt = new DataTable(); adapter.Fill(dt); sc.dgClientLog.DataSource = dt;
你的搜索结果验证逻辑可以保持不变:
SearchClientDataGrid(sc); if (sc.dgClientLog.Rows.Count == 0) { sc.NoItemFoundLabel.Visible = true; sc.NoItemFoundLabel.BringToFront(); return; } else { sc.NoItemFoundLabel.Visible = false; }
额外说明
如果你想要的是精确匹配而非包含匹配,直接去掉SQL里的concat,改成name = @search即可,但从你的代码来看,包含匹配是你需要的逻辑,所以上面的方案更适配。另外,转义时要注意MySQL的默认转义规则,默认情况下反斜杠是有效的转义字符,无需额外调整SQL模式。
这样调整后,用户输入的%David会被当成普通字符串去匹配,不再触发通配符功能,同时依然保留了参数化查询的防注入特性。
内容的提问来源于stack exchange,提问作者Akagami Shanks
相关产品推荐
相关产品推荐

