如何用sqlite3实现带列表的字典式数据存储?
正确的SQLite表结构设计
你的现有思路把多个理由打包成Blob存储并不合适——这种方式没法单独处理单条过期理由,也不便于查询和维护。正确的设计应该是把每条理由作为独立记录存储,同时增加created_at字段标记理由的添加时间,这样才能通过定时任务精准清理过期项。
创建表的代码如下:
import sqlite3 from datetime import datetime # 连接数据库(不存在则自动创建) conn = sqlite3.connect('user_reasons.db') cursor = conn.cursor() # 创建表:每条记录对应一个用户的单条理由 cursor.execute(""" CREATE TABLE IF NOT EXISTS user_reasons ( id INTEGER PRIMARY KEY AUTOINCREMENT, # 自增主键,唯一标识每条记录 userID TEXT NOT NULL, # 用户ID reason TEXT NOT NULL, # 理由内容 created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP # 理由添加时间,默认当前时间 ) """) conn.commit()
核心操作示例
1. 添加理由
给指定用户新增一条理由,自动记录当前时间:
def add_reason(user_id, reason): cursor.execute("INSERT INTO user_reasons (userID, reason) VALUES (?, ?)", (user_id, reason)) conn.commit() # 调用示例:给用户"12345"添加违规理由 add_reason("12345", "发布广告内容")
2. 查询用户的有效理由
获取指定用户当前未过期(未超过12小时)的所有理由:
def get_active_reasons(user_id): # 计算12小时前的时间点 twelve_hours_ago = datetime.now() - datetime.timedelta(hours=12) # 转换为SQLite可识别的时间格式 time_str = twelve_hours_ago.strftime("%Y-%m-%d %H:%M:%S") cursor.execute("SELECT reason FROM user_reasons WHERE userID = ? AND created_at > ?", (user_id, time_str)) return [row[0] for row in cursor.fetchall()] # 调用示例:获取用户"12345"的有效理由列表 active_reasons = get_active_reasons("12345")
3. Discord.py定时清理过期理由
用discord.py的tasks装饰器创建定时任务,比如每小时自动清理一次过期记录:
from discord.ext import tasks, commands bot = commands.Bot(command_prefix="!", intents=...) @tasks.loop(hours=1) async def clean_expired_reasons(): twelve_hours_ago = datetime.now() - datetime.timedelta(hours=12) time_str = twelve_hours_ago.strftime("%Y-%m-%d %H:%M:%S") # 执行删除操作 cursor.execute("DELETE FROM user_reasons WHERE created_at <= ?", (time_str,)) conn.commit() print(f"已清理{cursor.rowcount}条过期理由") # 机器人启动时开启定时任务 @bot.event async def on_ready(): clean_expired_reasons.start()
为什么不推荐用Blob存储理由列表?
- 无法单独删除单条过期理由,只能批量删除用户的所有理由,不符合需求
- 查询时需要先反序列化Blob,效率低且容易出现格式错误
- 不利于后续功能扩展(比如统计理由类型、修改单条理由等)
内容的提问来源于stack exchange,提问作者user19708585
相关产品推荐
相关产品推荐

