AIGC 时代,数据库终于可以“听懂人话”了:从零打造自然语言操作 SQLite 的完整实战

AIGC 时代,数据库终于可以"听懂人话"了:从零打造自然语言操作 SQLite 的完整实战

一、开场:为什么 2025 年的我们还在手写 SQL?

2024 年我还在苦苦背 LEFT JOIN ON 的各种坑,2025 年我已经可以用中文直接跟数据库聊天了:

"帮我把销售部门的黄佳工资改成 6 万,再加一个新员工张三,工程部,8 万块,最后把所有工程部员工按工资降序给我看一下"

10 秒后,数据库就乖乖执行完了,连一个分号都不用我打。

这不是科幻,这是今天你用几行 Python + 免费大模型就能实现的现实。

本文将手把手带你实现一个完整的「自然语言 → SQL → 执行 → 返回结果」的闭环,全程基于本地 SQLite + DeepSeek/Grok/Gemini 任意免费模型可跑通,代码不到 100 行,却能彻底改变你对数据库的认知。

二、传统 SQL 的痛,我们都懂

  • 业务同学提需求:"能不能把上个月注册且消费超过 500 的用户导个表?"
  • 程序员:"稍等,我写 SQL......"
  • 十分钟后交上去,结果列名是 user_id,业务表示看不懂
  • 改成"用户 ID"再导一遍 Excel
  • 再改需求、再写 SQL、再导出......

这流程在 2025 年看起来像原始人用石头砸核桃。

而 AIGC 时代,正确的打开方式是:

业务直接在企业微信/飞书里@机器人:"把上个月注册且消费超过 500 的用户导个表,要中文列名" 机器人秒回 Excel 文件,完毕。

这就是 Text-to-SQL 带来的降维打击。

二、SQLite 为什么是 AIGC 时代的最佳搭档?

1. 零配置、本地单文件、开箱即用

text

复制代码
test.db   ← 就一个文件,复制、备份、发微信都行

微信、飞书、Notion、Obsidian、桌面软件... 全都在用 SQLite,你甚至可以直接把公司核心数据放里面,完全不用装 MySQL。

2. Python 内置,无需 pip install

Python

python 复制代码
import sqlite3   # 原生自带,谁用谁知道

3. SQLite 的核心操作全解析(重点!)

操作 代码示例 关键点提醒
连接数据库 conn = sqlite3.connect("test.db") 路径可以是 :memory:(纯内存)
创建游标 cur = conn.cursor() 所有 SQL 都靠游标执行
执行建表 cur.execute("CREATE TABLE ...") IF NOT EXISTS 防止重复创建
插入单条 cur.execute("INSERT INTO t VALUES(?,?,?)", data) 用 ? 占位符,永远防注入
批量插入 cur.executemany("INSERT ...", list_of_tuples) 性能飞起,推荐!
查询 cur.execute("SELECT ...") → cur.fetchall() fetchone() / fetchmany(n)
获取列名 cur.description → [col[0] for col in cur.description] 动态列名必备
提交事务 conn.commit() 不 commit 等于没执行!
关闭连接 conn.close() 必须关闭,否则文件锁死

核心内容比喻解析

1. conn(Connection)------ 你和银行的"连接通道"

Python

ini 复制代码
conn = sqlite3.connect("company.db")
  • 它是"你和数据库之间的一条专线"。
  • 有了它你才能跟数据库说话。
  • 一条连接可以同时开多个窗口(多个 cursor)。

2. cursor(游标)------ 真正的"数据库操作员"

Python

ini 复制代码
cur = conn.cursor()
  • 可以把 cursor 想象成银行柜台里的那位漂亮柜员姐姐。
  • 所有 SQL 语句都是你"口头告诉她",然后她去电脑上敲。
  • 一个 conn 可以创建无数个 cursor(相当于银行开了好几个窗口)。

3. execute / executemany / executescript ------ 柜员的"三板斧"

方法 口头禅(你跟柜员说) 实际作用 推荐场景
cursor.execute(sql, params) "帮我存一笔钱,户名张三,金额80000" 执行一条 SQL,带参数最安全 增删改查单条记录
cursor.executemany(sql, list_of_params) "这100个人每人存5万,按名单来" 批量执行同一条 SQL,性能爆炸 导入 Excel、初始化数据
cursor.executescript(sql_script) "把这整页操作说明全部执行一遍" 执行一大段带分号的多个 SQL(建表+插入+索引) 数据库初始化脚本

真实代码对比,一看就懂

Python

python 复制代码
```python
# 情况1:插入一条
cur.execute("INSERT INTO employees (name, salary) VALUES (?, ?)", ("李四", 60000))

# 情况2:插入1000条(推荐用 executemany,速度快50倍!)
data = [("王五", 55000), ("赵六", 70000), ...]   # 1000条
cur.executemany("INSERT INTO employees (name, salary) VALUES (?, ?)", data)

# 情况3:初始化数据库(一大段脚本)
cur.executescript("""
    DROP TABLE IF EXISTS temp;
    CREATE TABLE temp(id int);
    INSERT INTO temp VALUES(1);
    INSERT INTO temp VALUES(2);
""")

重要提醒:主键一定要用 INTEGER PRIMARY KEY

SQL

sql 复制代码
id INTEGER PRIMARY KEY AUTOINCREMENT   -- 自动递增,省心
-- 或者简写
id INTEGER PRIMARY KEY                -- 同样自动递增(SQLite 特性)

三、核心思路:给大模型三件东西,它就能完美写 SQL

大模型写 SQL 其实非常简单,只需要喂它三样东西:

  1. 表结构(Schema)
  2. 明确的任务指令(自然语言问题)
  3. 严格的输出格式要求(只输出纯 SQL,禁止 Markdown)

缺一不可,缺了就翻车。

关键点 1:Schema 怎么喂最有效?

很多人直接把 PRAGMA table_info() 的原始列表扔给模型,结果长这样:

python 复制代码
[(0, 'id', 'INTEGER', 0, None, 1), (1, 'name', 'TEXT', 0, None, 0), ...]

模型看到一堆元组,懵了。

正确做法是转成类 CREATE TABLE 语句:

python 复制代码
CREATE TABLE employees (
    id INTEGER PRIMARY KEY,
    name TEXT,
    department TEXT,
    salary INTEGER
)

这样模型秒懂!因为它在预训练的时候见过无数这样的建表语句。

那么他是怎么实现的呢?

一键变形的关键!列表推导式到底干了什么?

swift 复制代码
schema_str = "CREATE TABLE EMPLOYEES (\n" + "\n".join([f"{col[1]} {col[2]}" for col in schema]) + "\n)"

我们把这行拆成 5 个小动作:

步骤 代码 作用 结果示例
1 for col in schema 遍历每一列的原始信息 col = (0, 'id', 'INTEGER', 0, None, 1)
2 col[1] 取出列名(第2个元素) 'id'
3 col[2] 取出列类型(第3个元素) 'INTEGER'
4 f"{col[1]} {col[2]}" 把列名+类型拼成一行 'id INTEGER'
5 [ ... for col in schema] 把所有列都这么拼 → 得到一个列表 ['id INTEGER', 'name TEXT', 'department TEXT', 'salary INTEGER']
6 "\n".join(...) 用换行符把列表连起来 id INTEGER\nname TEXT\n...
7 外面再包一层 CREATE TABLE 最终大功告成! 完整建表语句

最终输出:

SQL

sql 复制代码
CREATE TABLE EMPLOYEES (
id INTEGER
name TEXT
department TEXT
salary INTEGER
)

虽然还不够完美(没有 PRIMARY KEY、NOT NULL),但已经比原始元组提升了 1000% 的可读性,大模型准确率直接从 60% 跳到 95%+。

关键点 2:Prompt 必须"死板"才靠谱

python 复制代码
prompt = f"""
你是一个专业的 SQLite 专家。
以下是数据库表结构:

{schema_str}

请根据用户问题生成一条可直接执行的 SQLite 语句。
要求:
1. 只输出 SQL 语句本身
2. 不要用 Markdown 代码块
3. 不要加反引号
4. 不要解释,不要说明

用户问题:{question}
"""

温度建议设 0 或 0.1,越"死板"越稳定。

关键点 3:执行前一定要"审查"一下(防注入)

虽然我们是本地数据库,但养成好习惯:

python 复制代码
# 简单白名单常见危险操作
dangerous_keywords = ['DROP', 'DELETE', 'TRUNCATE', 'ALTER', 'CREATE', 'INSERT']
if any(kw in sql.upper() for kw in dangerous_keywords):
    print("检测到高危操作,请手动确认:")
    print(sql)
    if input("确认执行?(y/N): ").lower() != 'y':
        return

关键点 4: ?占位符

1.? 占位符到底有多牛?一句话总结

只要用了 ? 占位符,任何用户输入都不可能变成 SQL 命令,只能老老实实当数据。 这是 Python + SQLite/MySQL/PostgreSQL 官方推荐的、唯一 100% 防注入的方式。

2.经典注入 vs 用了 ? 后的真实效果
用户输入(黑客/运营) 危险拼接写法(必炸) 正确 ? 占位符写法(完全不炸)
黄佳'; DROP TABLE employees; -- WHERE name = '黄佳'; DROP TABLE employees; --' WHERE name = '黄佳'; DROP TABLE employees; --'
admin' OR '1'='1 登录绕过,查出所有用户 只查名字叫 "admin' OR 1=1" 的人 → 查不到,安全!
小明'); DELETE FROM users; -- 先插入小明,再把 users 表删光 插入一个名字叫 "小明'); DELETE FROM users; --" 的人

结论:用了 ? 后,黑客再牛逼的 payload,也只是你表里一个沙雕名字。

3.底层原理

sqlite3(以及所有主流数据库驱动)在执行时分两步走:

  1. 先把 SQL 模板发给数据库引擎(只带 ?

    SQL

    sql 复制代码
    SELECT * FROM users WHERE name = ?
  2. 参数走完全独立的二进制协议通道传过去,永远不和 SQL 文本混在一起

  3. 数据库引擎收到参数后,直接做「数据绑定」,根本不走 SQL 解析器

  4. 自动转义单引号 → ',整个参数变成一个完整的字符串字面量

相当于: 黑客写的是「核弹指令」,你硬生生给他包装成了「核弹形状的文字」,扔进数据库也只是个字符串。

四、进阶:让它返回美观的中文表格

大模型不止能写 SQL,还能直接帮你格式化结果:

python 复制代码
def pretty_print(results, cursor):
    if not results:
        return "暂无数据"
    # 获取列名
    columns = [desc[0] for desc in cursor.description]
    # 让大模型把结果转成 Markdown 表格
    prompt = f"把下面的数据转成美观的中文 Markdown 表格,列名翻译成中文:\n数据:{results}"
    columns}"
    # 调用大模型省略
    return markdown_table

这样你直接把结果发给领导,对方都怀疑你请了专职数据分析师。

五、真实场景落地建议

  1. 企业内部工具

    把这个做成飞书/企业微信机器人,非技术同学也能自助查数据,极大降低开发同学负担。

  2. 个人博客/小工具后台

    再也不用写 CRUD 页面了,直接聊天管理文章、留言、用户。

  3. 教育培训

    学生用自然语言操作数据库,门槛直线下降,SQL 教学可以直接跳过语法阶段。

六、常见坑 & 避坑指南

场景 容易出错写法 推荐写法
Schema 喂得不标准 直接给 PRAGMA 结果 转成 CREATE TABLE 语句
中文部门名乱码 没处理编码 SQLite 默认支持 UTF-8,无需担心
DELETE 没加 WHERE DELETE FROM users 必须加 WHERE,程序里强制审查
LIMIT 写错 LIMIT 2,5(MySQL 语法) SQLite 是 LIMIT 5 OFFSET 2
字段大小写问题 where Name = '张三' SQLite 字段名大小写不敏感,但建议统一

七、最后

2025 年的程序员,不再是"敲代码的",而是"会调度 AI 的"。

SQL 不会被淘汰,但"手写 SQL"这件事,大概率会像当年"手写汇编"一样,成为极少数人的浪漫。

未来已来,你准备好了吗?

相关推荐
坤岭3 分钟前
Python内存溢出问题
python
三木彤4 分钟前
Python 反爬 UA 检测真实案例(3个典型场景,可复现、合法合规)
python
SCBAiotAigc4 分钟前
MinerU离线推理
人工智能·python·mineru
94620164zwb55 分钟前
关于应用模块 Cordova 与 OpenHarmony 混合开发实战
python·学习
趁月色小酌***6 分钟前
JAVA 知识点总结5
java·开发语言·python
natide19 分钟前
表示/嵌入差异-1-欧几里得距离(Euclidean Distance)-L2 距离(L2 distance)-欧式距离的标准化
人工智能·pytorch·python·深度学习·算法·自然语言处理
对方正在长头发丿22 分钟前
Numpy学习篇
python·学习·jupyter·pycharm·numpy
Elaine33627 分钟前
深度实战:基于 Scrapy CrawlSpider 的全自动化教程采集系统
python·scrapy·自动化·网络爬虫
2401_8414956436 分钟前
【游戏开发】登山赛车
数据结构·python·游戏·游戏开发·pygame·登山赛车游戏·游戏打包发布
心无旁骛~44 分钟前
[SO101]在Jetson AGX Thor 上训练和部署GROOT N1.5模型
python·机器人