You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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(); }
}

问题分析

  1. 初始代码问题:
    将多个URL拼接成单个字符串作为参数传入,但SQL的IN子句无法识别单个字符串参数内的多个值,它会把整个拼接后的字符串当作一个完整的匹配项,自然找不到对应记录。

  2. 更新后代码问题:

    • 直接拼接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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 13:55:16