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"这件事,大概率会像当年"手写汇编"一样,成为极少数人的浪漫。

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

相关推荐
Q_Q5110082851 小时前
python+django/flask+vue农业电商服务系统
spring boot·python·pycharm·django·flask
帕巴啦1 小时前
Python计算累积频率——Origin绘制累积频率图
python·绘图·origin·累积频率·python计算累积频率·origin绘制累积频率图
Q_Q5110082851 小时前
python+django/flask+vue的基于疫情防控管理系统的数据可视化分析系统
spring boot·python·django·flask·node.js
生信大表哥1 小时前
Claude Code / Gemini CLI / Codex CLI 安装大全(Linux 服务器版)
linux·python·ai·r语言·数信院生信服务器
databook1 小时前
用样本猜总体的秘密武器,4大抽样分布总结
后端·python·数据分析
Jacob程序员1 小时前
欧几里得距离算法-相似度
开发语言·python·算法
a man of sadness1 小时前
GPS轨迹抽稀:降频、滑动窗口、RDP
python·gps·轨迹·抽稀·rdp算法
网安老伯1 小时前
什么是网络安全?网络安全包括哪几个方面?学完能做一名黑客吗?
linux·数据库·python·web安全·网络安全·php·xss
天才测试猿2 小时前
Postman接口测试:如何导入swagger接口文档?
自动化测试·软件测试·python·测试工具·职场和发展·接口测试·postman