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

Python中SQLite执行ALTER TABLE时出现关联SELECT语句的KeyError问题

问题分析与解决

你的错误看似矛盾——ALTER TABLE语句触发了KeyError,但错误信息却指向更早的SELECT语句,根源在于你在多线程中共享了同一个SQLite连接,导致了未定义的内存/状态混乱。

SQLite连接本身并非线程安全,哪怕设置了check_same_thread=False,也只是关闭了线程安全检查,并没有让连接具备多线程安全能力。多个线程同时操作同一连接会引发各种诡异问题:比如SQL语句被混淆、变量值被意外覆盖,就像你遇到的情况——主线程中的row变量(表名)被线程中的SELECT语句内容污染,最终导致格式化ALTER TABLE语句时触发KeyError。

修复步骤

1. 线程操作使用独立连接

让每个线程创建自己的SQLite连接,不要共享主线程的连接:

def get_data(number2, table_name, dataset):
    column = "id"
    # 每个线程独立创建连接
    thread_con = sl.connect(dataset, check_same_thread=False)
    try:
        creation_time = thread_con.execute(
            "SELECT FileCreationTime,{} FROM {} WHERE file_number = ?;".format(column, table_name),
            (int(number2),)
        ).fetchall()
    except Exception as e:
        print(column, table_name, int(number2), e)
        raise
    finally:
        thread_con.close()  # 用完及时关闭
    
    if len(creation_time) > 1:
        time_list = [item[0] for item in creation_time]
        id_list = [item[1] for item in creation_time]
        # 按时间排序后的id列表
        sorted_ids = [x for _, x in sorted(zip(time_list, id_list))]
        # 用锁保护全局字典,避免竞态条件
        with lock:
            time_1[str(number2)] = sorted_ids

同时在主线程中添加锁,保护多线程共享的time_1字典:

# 在定义time_1前初始化锁
lock = threading.Lock()
time_1 = {}

启动线程时传入数据集路径:

t1 = threading.Thread(target=get_data, args=(a1, row, dataset))

2. 避免SQL注入,使用参数化查询

你的UPDATE语句直接格式化字符串,存在注入风险且易出错,改成参数化写法:

con.execute(
    "UPDATE {} SET duplicate = ? WHERE id = ?;".format(row),
    (i, n)
)

注:表名无法用参数化,所以format(row)是安全的(表名来自sqlite_master,为可信值)。

3. 可选:改用单线程处理(简单安全)

如果数据量不是极大,直接去掉多线程逻辑,单线程处理更稳定,无需处理锁和多连接:

# 替换原多线程代码块
for number2 in tqdm(position[:50]):
    get_data(number2, row)

其他小问题修正

  • file_number是整数类型,用=代替LIKE更符合逻辑;
  • 你仅处理了position[:50](前50个file_number),若需处理所有重复项,去掉切片即可。

内容的提问来源于stack exchange,提问作者Piotr Yartsev

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 09:24:41