AIGC 时代,用自然语言操作数据库:SQLite + LLM 的轻量级实践

AIGC 时代,用自然语言操作数据库:SQLite + LLM 的轻量级实践


一、为什么我们需要"自然语言查数据库"?

SQL 是结构化查询语言,精准但门槛不低。对于产品经理、运营、测试甚至初级开发者来说,写一条 JOINGROUP BY 可能比写周报还难。

而如今,大语言模型(如 DeepSeek、GPT、Claude 等)已经具备极强的语义理解与代码生成能力。只要给它清晰的数据库结构(Schema)和一句自然语言问题,它就能生成准确的 SQL。

这不仅是效率工具,更是人机协作范式的升级

你负责"想问什么",AI 负责"怎么查"。


二、为什么选择 SQLite?

在众多数据库中,SQLite 是轻量级场景的王者:

  • 零配置、单文件 :整个数据库就是一个 .db 文件,无需安装服务。
  • 嵌入式友好:微信、Chrome、Android 系统内部都用它做本地存储。
  • 标准 SQL 支持:支持大部分 SQL 语法,足以应对日常 CRUD。
  • Python 原生支持import sqlite3 即可开干,无额外依赖。

💡 对比 MySQL/PostgreSQL:它们适合高并发、分布式场景,但对本地工具、桌面应用、原型开发来说"杀鸡用牛刀"。


三、动手实践:5 分钟搭建"自然语言查库"系统

1. 创建数据库与表

python 复制代码
# 轻量级数据库
import sqlite3
from openai import OpenAI

# ========== 1. 连接数据库(仅一次)==========
conn = sqlite3.connect("test1.db")
cursor = conn.cursor()

# ========== 2. 创建表 ==========
cursor.execute("""
CREATE TABLE IF NOT EXISTS employees (
    id INTEGER PRIMARY KEY,
    name TEXT,
    department TEXT,
    salary INTEGER
)
""")

2. 插入示例数据

scss 复制代码
# ========== 3. 插入示例数据 ==========
sample_data = [    (1, "陈", "开发部", 32000),    (2, "张", "销售部", 20000),    (3, "徐", "开发部", 33000),    (4, "李", "销售部", 15000)]
cursor.executemany('INSERT OR IGNORE INTO employees VALUES (?, ?, ?, ?)', sample_data)
conn.commit()

✅ 使用 INSERT OR IGNORE 避免重复插入导致主键冲突。

3. 获取表结构(Schema)

这是 LLM 理解数据库的关键上下文:

python 复制代码
# ========== 4. 获取 Schema(统一用小写表名)==========
schema = cursor.execute("PRAGMA table_info(employees)").fetchall()
schema_str = "CREATE TABLE employees (\n" + "\n".join([f"  {col[1]} {col[2]}" for col in schema]) + "\n);"
print("数据库Schema:")
print(schema_str)

输出:

sql 复制代码
数据库Schema:
CREATE TABLE employees (
  id INTEGER
  name TEXT
  department TEXT
  salary INTEGER
);

✅ 表名统一为小写 employees,符合 SQLite 实际建表习惯,避免大小写混淆。

4. 接入 LLM(以 DeepSeek 为例)

ini 复制代码
# ========== 5. 接入 LLM ==========
client = OpenAI(
    api_key='你的 API Key',
    base_url='https://api.deepseek.com/v1'
)

def ask_deepseek(query: str, schema: str) -> str:
    prompt = f"""
这是一个数据库的Schema:
{schema}
根据这个Schema,你能输出一个SQL查询来回答以下问题吗?
只输出SQL查询,不要输出任何其他内容,也不要带任何格式。
问题:{query}
"""
    response = client.chat.completions.create(
        model="deepseek-reasoner",
        max_tokens=256,
        messages=[{"role": "user", "content": prompt}]
    )
    # ✅ 关键:返回纯 SQL 字符串
    return response.choices[0].message.content.strip()

🔑 注意:函数最终返回的是 .content.strip(),确保是干净的 SQL 字符串,而非 ChatCompletionMessage 对象。

5. 自然语言提问 → 执行 SQL

python 复制代码
# ========== 6. 自然语言提问 → 生成并执行 SQL ==========
question = "开发部部门员工的姓名和工资是多少?"
generated_sql = ask_deepseek(question, schema_str)
print("\n生成的SQL查询:")
print(generated_sql)

# ✅ 安全提示:此处仅为演示!生产环境需校验SQL
try:
    result = cursor.execute(generated_sql).fetchall()
    print("\n查询结果:")
    for row in result:
        print(row)
except Exception as e:
    print(f"\n执行出错: {e}")

典型输出:

sql 复制代码
生成的SQL查询:
SELECT name, salary FROM employees WHERE department = '开发部';

查询结果:
('陈', 32000)
('徐', 33000)

✅ 成功!你用中文问问题,AI 自动生成 SQL 并返回结果。

6. 关闭连接(良好习惯)

bash 复制代码
# ========== 7. 关闭连接 ==========
conn.close()

四、Prompt 工程:让 LLM 更可靠

LLM 不是万能的,好的 Prompt 是稳定输出的关键。我们通过以下设计提升准确性:

技巧 说明
明确 Schema 上下文 必须提供表结构,否则 LLM 会"瞎猜字段"
限制输出格式 "只输出 SQL,不要其他内容" 避免冗余
指定大小写与引号 统一表名小写、字符串用单引号,减少语法错误
示例引导(Few-shot) 可追加 1~2 个输入-输出样例,效果更佳

🔒 安全警告

上述代码中的 cursor.execute(generated_sql) 直接执行 LLM 输出的 SQL,存在严重安全风险 (如 SQL 注入、DROP TABLE 等)。

在真实项目中,务必:

  • 使用 白名单机制(只允许 SELECT,禁止 DDL/DML)
  • 对生成的 SQL 进行 AST 解析校验
  • 或采用 参数化查询模板,仅让 LLM 填充 WHERE 条件部分
相关推荐
纤纡.10 分钟前
PyTorch 入门精讲:从框架选择到 MNIST 手写数字识别实战
人工智能·pytorch·python
2601_9495936516 分钟前
深入解析CANN-acl应用层接口:构建高效的AI应用开发框架
数据库·人工智能
javachen__17 分钟前
mysql新老项目版本选择
数据库·mysql
kjkdd21 分钟前
6.1 核心组件(Agent)
python·ai·语言模型·langchain·ai编程
VT.馒头24 分钟前
【力扣】2695. 包装数组
前端·javascript·算法·leetcode·职场和发展·typescript
小镇敲码人28 分钟前
剖析CANN框架中Samples仓库:从示例到实战的AI开发指南
c++·人工智能·python·华为·acl·cann
萧鼎29 分钟前
Python 包管理的“超音速”革命:全面上手 uv 工具链
开发语言·python·uv
Dxy123931021635 分钟前
MySQL如何高效查询表数据量:从基础到进阶的优化指南
数据库·mysql
css趣多多36 分钟前
一个UI内置组件el-scrollbar
前端·javascript·vue.js
Dying.Light38 分钟前
MySQL相关问题
数据库·mysql