C#实现SQLite表批量删除多行失败,请求排查代码问题
C# SQLite批量删除多行失效问题排查与解决
问题描述
我在查找C#实现SQLite表批量删除多行的方法,拼接了自认为可行的代码,但实际运行无效。RemoveLinks方法始终返回0条记录被删除且无错误提示,需求为仅删除URL列匹配列表中任意URL字符串的行(URL列唯一但非主键)。
初始代码
public static int RemoveLinks(string table, List<string> urls) { SQLiteConnection sqlite_conn; sqlite_conn = CreateConnection(); try { var urlsString = string.Join(",", urls.Select(p => p)); var deleteQuery = string.Format("delete from {0} where {1} in ({2})", table, "url", "@urlsStr"); SQLiteCommand sqlite_cmd; sqlite_cmd = sqlite_conn.CreateCommand(); sqlite_cmd.CommandText = deleteQuery; sqlite_cmd.Parameters.Add(new SQLiteParameter("@urlsStr", urlsString)); int rslt = sqlite_cmd.ExecuteNonQuery(); sqlite_conn.Close(); return rslt; } catch (Exception e) { sqlite_conn.Close(); MessageBox.Show(e.Message); return 0; } }
更新后代码(仍失效)
根据建议修改代码后,仍无法删除记录:
public static bool RemoveLinks(string table, List<string> urls) { bool result = false; SQLiteConnection sqlite_conn; sqlite_conn = CreateConnection(); try { var urlsString = string.Join(",", urls); var deleteQuery = string.Format("delete from {0} where {1} in ('{2}')", table, "url", urlsString); SQLiteCommand sqlite_cmd = sqlite_conn.CreateCommand(); sqlite_cmd.CommandText = deleteQuery; var rslt = sqlite_cmd.ExecuteScalar(); result = (rslt != null); return result; } catch (Exception e) { MessageBox.Show(e.Message); return result; } finally { sqlite_conn.Close(); } }
问题分析
初始代码问题:
将多个URL拼接成单个字符串作为参数传入,但SQL的IN子句无法识别单个字符串参数内的多个值,它会把整个拼接后的字符串当作一个完整的匹配项,自然找不到对应记录。更新后代码问题:
- 直接拼接URL到SQL语句中,若URL包含单引号等特殊字符,会直接导致SQL语法错误;同时存在SQL注入风险。
- 使用
ExecuteScalar()执行DELETE语句是错误的,该方法用于返回查询结果的第一行第一列,而DELETE语句不会返回任何结果,因此rslt始终为null,导致返回错误的false结果,即使删除成功也无法正确判断。
正确实现方案
采用动态生成参数的方式,为每个URL创建独立参数,既保证SQL语法正确,又避免注入风险:
public static int RemoveLinks(string table, List<string> urls) { if (urls == null || urls.Count == 0) return 0; using (var sqlite_conn = CreateConnection()) { try { // 为每个URL生成独立的参数占位符 var paramPlaceholders = urls.Select((_, idx) => $"@url{idx}").ToList(); var deleteQuery = $"DELETE FROM {table} WHERE url IN ({string.Join(", ", paramPlaceholders)})"; using (var sqlite_cmd = sqlite_conn.CreateCommand()) { sqlite_cmd.CommandText = deleteQuery; // 逐个添加URL参数 for (int i = 0; i < urls.Count; i++) { sqlite_cmd.Parameters.AddWithValue($"@url{i}", urls[i]); } // 执行删除并返回受影响行数 return sqlite_cmd.ExecuteNonQuery(); } } catch (Exception e) { MessageBox.Show(e.Message); return 0; } } }
方案说明
- 使用
using语句自动管理数据库连接和命令的生命周期,无需手动调用Close(),避免资源泄漏。 - 为每个URL创建独立参数,确保
IN子句能正确匹配多个值。 - 通过
ExecuteNonQuery()获取受影响的行数,这是执行DELETE/INSERT/UPDATE语句的标准方式,能准确反映删除操作的结果。
内容的提问来源于stack exchange,提问作者Khalid Almannai
相关产品推荐
相关产品推荐

