🚀

用 Ollama 搭一个 AI SQL 翻译器:自然语言查数据库,不用学 SQL

把查一下上个月销售额最高的10个产品变成 SQL,零门槛。本地 Ollama 运行,数据不上传,免费又安全。

👁️ - 次阅读

老板突然问:“上个月销售额最高的10个产品是哪些?”

你盯着数据库发愁——表结构复杂,SQL 写得慢,还要担心写错影响线上。

自然语言查数据库,听起来像魔法。其实用 Ollama 搭一个本地 SQL 翻译器,数据完全留在自己服务器上,免费、安全、零依赖。

今天教你从零搭一个 AI SQL 翻译器。

项目背景

数据库查询是数据分析的核心动作。但大多数人不会写 SQL,或者写得很慢。

传统方案有两个极端:

  • 找开发人员帮忙:排队等半天,需求还变来变去
  • 买 BI 工具:贵,而且复杂,小团队用不上

AI SQL 翻译器填上了这个空白。你只需用自然语言描述需求,它自动生成 SQL,执行后返回结果。

这个项目的核心思路:

自然语言 → AI 理解意图 → 生成 SQL → 执行查询 → 返回结果

全部在本地跑,不上传任何数据。

技术选型

组件选择理由
语言Python 3.10+脚本友好,库丰富
LLMOllama + qwen2.5:7b代码能力强,本地免费
数据库连接sqlite3零配置,开箱即用
交互方式命令行 + 简单 API灵活,易扩展

不需要外部 API Key,不需要付费服务。Ollama 跑起来就能用。

实现步骤

第一步:安装依赖

# 安装 Ollama(如果还没装)
curl -fsSL https://ollama.ai/install.sh | sh

# 拉取模型
ollama pull qwen2.5:7b

# 启动 Ollama 服务
ollama serve &

# 安装 Python 依赖
pip install ollama sqlite3-utils

第二步:创建示例数据库

先建一个带示例数据的 SQLite 数据库,方便测试:

# setup_db.py
import sqlite3
from datetime import datetime, timedelta

conn = sqlite3.connect("shop.db")
cursor = conn.cursor()

# 创建表
cursor.execute("""
CREATE TABLE IF NOT EXISTS products (
    id INTEGER PRIMARY KEY,
    name TEXT NOT NULL,
    category TEXT,
    price REAL
)
""")

cursor.execute("""
CREATE TABLE IF NOT EXISTS orders (
    id INTEGER PRIMARY KEY,
    product_id INTEGER,
    quantity INTEGER,
    order_date TEXT,
    FOREIGN KEY (product_id) REFERENCES products(id)
)
""")

# 插入示例数据
products = [
    (1, "MacBook Pro", "电脑", 12999),
    (2, "iPhone 15", "手机", 7999),
    (3, "AirPods Pro", "耳机", 1899),
    (4, "iPad Air", "平板", 4799),
    (5, "Apple Watch", "手表", 2999),
    (6, "Magic Keyboard", "配件", 999),
    (7, "Studio Display", "显示器", 11499),
    (8, "Mac Mini", "电脑", 4499),
    (9, "HomePod", "音箱", 1999),
    (10, "AirTag", "配件", 229),
]

orders = []
base_date = datetime(2026, 7, 1)
for i in range(200):
    day_offset = i % 31
    hour = i % 24
    order_date = (base_date + timedelta(days=day_offset)).strftime("%Y-%m-%d")
    product_id = (i % 10) + 1
    quantity = (i % 5) + 1
    orders.append((product_id, quantity, order_date))

cursor.executemany("INSERT INTO products VALUES (?, ?, ?, ?)", products)
cursor.executemany("INSERT INTO orders (product_id, quantity, order_date) VALUES (?, ?, ?)", orders)

conn.commit()
conn.close()
print("✅ 数据库初始化完成:shop.db")

运行:

python setup_db.py

第三步:写 SQL 翻译核心代码

# sql_translator.py
import sqlite3
import ollama
import json

MODEL = "qwen2.5:7b"

SYSTEM_PROMPT = """你是一个 SQL 专家。用户用自然语言描述需求,你生成正确的 SQL 查询语句。

规则:
1. 只输出 SQL,不要解释
2. SQL 以分号结尾
3. 如果需求不明确,询问具体字段或条件
4. 只查询不修改数据(SELECT,禁止 INSERT/UPDATE/DELETE)
5. 表结构如下:
   - products: id, name, category, price
   - orders: id, product_id, quantity, order_date
"""

def translate_to_sql(natural_query: str) -> str:
    """自然语言 → SQL"""
    response = ollama.chat(
        model=MODEL,
        messages=[
            {"role": "system", "content": SYSTEM_PROMPT},
            {"role": "user", "content": natural_query}
        ]
    )
    sql = response["message"]["content"].strip()
    # 清理可能的 markdown 代码块
    if sql.startswith("```"):
        sql = sql.split("\n", 1)[1].rsplit("```", 1)[0].strip()
    return sql


def execute_sql(db_path: str, sql: str) -> list:
    """执行 SQL 并返回结果"""
    conn = sqlite3.connect(db_path)
    conn.row_factory = sqlite3.Row
    cursor = conn.cursor()
    
    try:
        cursor.execute(sql)
        rows = cursor.fetchall()
        if cursor.description:
            columns = [desc[0] for desc in cursor.description]
            result = [dict(row) for row in rows]
            return {"columns": columns, "data": result, "count": len(result)}
        return {"columns": [], "data": [], "count": 0}
    except Exception as e:
        return {"error": str(e), "sql": sql}
    finally:
        conn.close()


def query(natural_query: str, db_path: str = "shop.db") -> dict:
    """完整流程:自然语言 → SQL → 结果"""
    print(f"\n📝 你的问题: {natural_query}")
    
    # 1. 翻译
    sql = translate_to_sql(natural_query)
    print(f"🤖 生成 SQL: {sql}")
    
    # 2. 执行
    result = execute_sql(db_path, sql)
    
    if "error" in result:
        print(f"❌ 执行失败: {result['error']}")
        return result
    
    print(f"📊 返回 {result['count']} 条记录")
    
    # 3. 格式化输出
    if result["data"]:
        print("\n" + "=" * 50)
        print(" | ".join(result["columns"]))
        print("=" * 50)
        for row in result["data"][:10]:  # 最多显示10条
            print(" | ".join(str(v) for v in row.values()))
        if result["count"] > 10:
            print(f"... 还有 {result['count'] - 10} 条记录")
    
    return result

第四步:交互式 CLI 入口

# main.py
import sys
from sql_translator import query

EXAMPLES = [
    "上个月销售额最高的10个产品",
    "每个类别的产品数量和平均价格",
    "7月份订单数量最多的日期",
    "价格超过5000的产品有哪些",
    "统计每个产品的总销售额",
]

def main():
    if len(sys.argv) > 1:
        # 命令行模式
        natural_query = " ".join(sys.argv[1:])
        result = query(natural_query)
    else:
        # 交互模式
        print("🧠 AI SQL 翻译器")
        print("输入自然语言问题,按 Ctrl+C 退出")
        print("示例问题:")
        for i, ex in enumerate(EXAMPLES, 1):
            print(f"  {i}. {ex}")
        print()
        
        while True:
            try:
                user_input = input("❓ 你的问题: ").strip()
                if not user_input:
                    continue
                if user_input.lower() in ("quit", "exit", "q"):
                    break
                query(user_input)
                print()
            except KeyboardInterrupt:
                print("\n👋 再见!")
                break

if __name__ == "__main__":
    main()

第五步:运行测试

# 先初始化数据库
python setup_db.py

# 交互模式运行
python main.py

# 或直接命令行
python main.py "上个月销售额最高的10个产品"

预期输出:

📝 你的问题: 上个月销售额最高的10个产品
🤖 生成 SQL: SELECT p.name, SUM(o.quantity * p.price) as total_sales
             FROM products p JOIN orders o ON p.id = o.product_id
             WHERE o.order_date >= '2026-07-01' AND o.order_date < '2026-08-01'
             GROUP BY p.id ORDER BY total_sales DESC LIMIT 10;
📊 返回 10 条记录

==================================================
name | total_sales
==================================================
iPhone 15 | 119985
MacBook Pro | 77994
Studio Display | 45497
...

运行效果

搭好之后,你的工作流变成这样:

日常业务问题 → 直接问 AI → 自动生成 SQL → 执行查询 → 拿到结果

不需要找开发,不需要学 SQL,5 秒出结果。

几个典型场景:

  • 运营同学:“上周新增用户多少?” → 自动生成 SELECT COUNT(*) FROM users WHERE create_date >= ...
  • 产品经理:“转化率最高的渠道是哪个?” → 自动关联多表查询
  • 老板:“最近30天哪个产品卖得最好?” → 自动聚合计算

数据全在本地,不上传任何信息。

优化方向

这个 MVP 已经能用,但还有很大提升空间:

  1. 多数据库支持:当前只支持 SQLite,可扩展到 PostgreSQL、MySQL、MongoDB
  2. SQL 校验:在生成后加一层语法检查,防止 AI 瞎编
  3. 结果可视化:查完直接画柱状图、折线图,不用再去 Tableau
  4. 对话上下文:支持多轮对话,“按类别再分一下"这种追问
  5. 缓存机制:相同问题不重复调用 API,节省 token
  6. Web 界面:包一个 FastAPI + 简单前端,团队共享
  7. 自动建表:输入业务场景描述,AI 自动设计表结构

要不要试试?把自己的数据库接上去,问几个问题看看效果。

# 快速开始
ollama pull qwen2.5:7b
pip install ollama
python main.py "你好,查一下今天的订单数"

你的数据库里,现在最缺一个什么样的查询?

这篇文章对你有帮助吗?