数据库Skill开发教程:从零构建SQLite应用

1. 数据库架构设计(图表描述)

图表说明:这是一个典型的电商数据库ER图,包含用户、产品和订单三个核心表。Users表存储用户信息,Products表管理商品数据,Orders表记录交易。外键关系确保数据完整性:订单必须关联到存在的用户和产品。

2. 环境准备与基础连接

复制代码
import sqlite3
import pandas as pd
import matplotlib.pyplot as plt
from datetime import datetime, timedelta

# 创建数据库连接
def create_connection(db_file):
    """创建数据库连接到SQLite数据库"""
    conn = None
    try:
        conn = sqlite3.connect(db_file)
        print(f"成功连接到SQLite数据库,版本: {sqlite3.version}")
        return conn
    except sqlite3.Error as e:
        print(f"连接数据库时出错: {e}")
    return conn

# 初始化数据库
def init_database():
    """初始化数据库并创建表结构"""
    conn = create_connection("ecommerce.db")
    cursor = conn.cursor()
    
    # 创建Users表
    cursor.execute('''
    CREATE TABLE IF NOT EXISTS users (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        name TEXT NOT NULL,
        email TEXT UNIQUE NOT NULL,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    )
    ''')
    
    # 创建Products表
    cursor.execute('''
    CREATE TABLE IF NOT EXISTS products (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        name TEXT NOT NULL,
        price REAL NOT NULL CHECK(price > 0),
        stock INTEGER NOT NULL DEFAULT 0,
        category TEXT NOT NULL,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    )
    ''')
    
    # 创建Orders表
    cursor.execute('''
    CREATE TABLE IF NOT EXISTS orders (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        user_id INTEGER NOT NULL,
        product_id INTEGER NOT NULL,
        quantity INTEGER NOT NULL CHECK(quantity > 0),
        order_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
        FOREIGN KEY (user_id) REFERENCES users(id),
        FOREIGN KEY (product_id) REFERENCES products(id)
    )
    ''')
    
    # 创建索引优化查询性能
    cursor.execute('CREATE INDEX IF NOT EXISTS idx_orders_user ON orders(user_id)')
    cursor.execute('CREATE INDEX IF NOT EXISTS idx_orders_date ON orders(order_date)')
    
    conn.commit()
    print("数据库表结构创建成功!")
    return conn

3. CRUD操作实现

复制代码
class DatabaseManager:
    def __init__(self, db_connection):
        self.conn = db_connection
        self.cursor = self.conn.cursor()
    
    # 用户管理
    def create_user(self, name, email):
        """创建新用户"""
        try:
            self.cursor.execute(
                "INSERT INTO users (name, email) VALUES (?, ?)",
                (name, email)
            )
            self.conn.commit()
            user_id = self.cursor.lastrowid
            print(f"用户创建成功,ID: {user_id}")
            return user_id
        except sqlite3.IntegrityError as e:
            print(f"创建用户失败: 邮箱地址重复 - {email}")
            return None
    
    def get_user(self, user_id):
        """获取用户信息"""
        self.cursor.execute("SELECT * FROM users WHERE id = ?", (user_id,))
        return self.cursor.fetchone()
    
    # 产品管理
    def add_product(self, name, price, stock, category):
        """添加新产品"""
        self.cursor.execute('''
        INSERT INTO products (name, price, stock, category)
        VALUES (?, ?, ?, ?)
        ''', (name, price, stock, category))
        self.conn.commit()
        return self.cursor.lastrowid
    
    def update_stock(self, product_id, quantity):
        """更新产品库存"""
        self.cursor.execute('''
        UPDATE products 
        SET stock = stock + ? 
        WHERE id = ? AND stock + ? >= 0
        ''', (quantity, product_id, quantity))
        
        if self.cursor.rowcount == 0:
            print(f"库存更新失败:产品ID {product_id}不存在或库存不足")
            return False
        
        self.conn.commit()
        return True
    
    # 订单管理
    def create_order(self, user_id, product_id, quantity):
        """创建新订单"""
        # 检查用户是否存在
        self.cursor.execute("SELECT id FROM users WHERE id = ?", (user_id,))
        if not self.cursor.fetchone():
            print(f"错误:用户ID {user_id}不存在")
            return None
        
        # 检查产品库存
        self.cursor.execute("SELECT stock FROM products WHERE id = ?", (product_id,))
        product = self.cursor.fetchone()
        if not product:
            print(f"错误:产品ID {product_id}不存在")
            return None
        
        if product[0] < quantity:
            print(f"错误:库存不足!当前库存: {product[0]},需要: {quantity}")
            return None
        
        # 创建订单
        self.cursor.execute('''
        INSERT INTO orders (user_id, product_id, quantity)
        VALUES (?, ?, ?)
        ''', (user_id, product_id, quantity))
        
        # 更新库存
        self.update_stock(product_id, -quantity)
        
        self.conn.commit()
        return self.cursor.lastrowid
    
    # 数据分析
    def get_sales_report(self, days=30):
        """获取销售报告"""
        start_date = datetime.now() - timedelta(days=days)
        self.cursor.execute('''
        SELECT 
            p.name as product_name,
            p.category,
            SUM(o.quantity) as total_quantity,
            SUM(o.quantity * p.price) as total_revenue
        FROM orders o
        JOIN products p ON o.product_id = p.id
        WHERE o.order_date >= ?
        GROUP BY p.id
        ORDER BY total_revenue DESC
        LIMIT 10
        ''', (start_date,))
        
        return self.cursor.fetchall()
    
    def close(self):
        """关闭数据库连接"""
        if self.conn:
            self.conn.close()
            print("数据库连接已关闭")

4. 可视化与数据分析

复制代码
def generate_visualizations(db_manager):
    """生成数据可视化图表"""
    # 获取销售数据
    sales_data = db_manager.get_sales_report(30)
    
    if not sales_data:
        print("没有销售数据可供可视化")
        return
    
    # 准备数据
    products = [row[0] for row in sales_data]
    revenues = [row[3] for row in sales_data]
    quantities = [row[2] for row in sales_data]
    
    # 创建图表
    plt.figure(figsize=(15, 10))
    
    # 收入排名图
    plt.subplot(2, 1, 1)
    bars = plt.bar(products, revenues, color='skyblue')
    plt.title('Top 10 产品收入排名 (30天)', fontsize=14, fontweight='bold')
    plt.xlabel('产品名称', fontsize=12)
    plt.ylabel('收入 (元)', fontsize=12)
    plt.xticks(rotation=45, ha='right')
    plt.grid(axis='y', alpha=0.3)
    
    # 在柱子上显示数值
    for bar in bars:
        height = bar.get_height()
        plt.text(bar.get_x() + bar.get_width()/2., height,
                f'¥{height:.2f}',
                ha='center', va='bottom', fontsize=9)
    
    # 销量与收入对比图
    plt.subplot(2, 1, 2)
    x = range(len(products))
    width = 0.35
    
    plt.bar([i - width/2 for i in x], quantities, width, label='销量', color='lightgreen')
    plt.bar([i + width/2 for i in x], [r/100 for r in revenues], width, label='收入(100元单位)', color='salmon')
    
    plt.title('销量与收入对比', fontsize=14, fontweight='bold')
    plt.xlabel('产品名称', fontsize=12)
    plt.ylabel('数量/收入单位', fontsize=12)
    plt.xticks(x, products, rotation=45, ha='right')
    plt.legend()
    plt.grid(axis='y', alpha=0.3)
    
    plt.tight_layout()
    plt.savefig('sales_report.png', dpi=300, bbox_inches='tight')
    plt.show()
    print("可视化图表已生成并保存为 'sales_report.png'")

5. 完整应用示例

复制代码
def main():
    """主应用函数"""
    print("=== 电商数据库管理系统 ===\n")
    
    # 初始化数据库
    conn = init_database()
    db_manager = DatabaseManager(conn)
    
    try:
        # 添加测试用户
        print("\n--- 添加测试用户 ---")
        user1 = db_manager.create_user("张三", "zhangsan@example.com")
        user2 = db_manager.create_user("李四", "lisi@example.com")
        user3 = db_manager.create_user("王五", "wangwu@example.com")
        
        # 添加测试产品
        print("\n--- 添加测试产品 ---")
        products = [
            ("智能手机", 2999.99, 50, "电子产品"),
            ("笔记本电脑", 8999.99, 30, "电子产品"),
            ("运动鞋", 599.99, 100, "服装"),
            ("咖啡机", 1299.99, 25, "家电"),
            ("图书", 49.99, 200, "文化用品")
        ]
        
        product_ids = []
        for name, price, stock, category in products:
            pid = db_manager.add_product(name, price, stock, category)
            product_ids.append(pid)
            print(f"产品 '{name}' 添加成功,ID: {pid}")
        
        # 创建测试订单
        print("\n--- 创建测试订单 ---")
        orders = [
            (user1, product_ids[0], 2),  # 张三买2个手机
            (user1, product_ids[2], 1),  # 张三买1双鞋
            (user2, product_ids[1], 1),  # 李四买1台电脑
            (user3, product_ids[3], 1),  # 王五买1台咖啡机
            (user2, product_ids[4], 5),  # 李四买5本书
            (user3, product_ids[0], 1),  # 王五买1个手机
            (user1, product_ids[1], 1),  # 张三买1台电脑
        ]
        
        for user_id, product_id, quantity in orders:
            order_id = db_manager.create_order(user_id, product_id, quantity)
            if order_id:
                user = db_manager.get_user(user_id)
                product = db_manager.cursor.execute("SELECT name FROM products WHERE id = ?", (product_id,)).fetchone()
                print(f"订单创建成功!用户: {user[1]}, 产品: {product[0]}, 数量: {quantity}")
        
        # 生成销售报告
        print("\n--- 生成销售报告 ---")
        sales_report = db_manager.get_sales_report(30)
        print("\n最近30天销售Top 10:")
        print("-" * 80)
        print(f"{'产品名称':<20} {'类别':<10} {'销量':<8} {'收入(元)':<12}")
        print("-" * 80)
        
        for row in sales_report:
            print(f"{row[0]:<20} {row[1]:<10} {row[2]:<8} ¥{row[3]:.2f}")
        
        # 生成可视化图表
        print("\n--- 生成数据可视化 ---")
        generate_visualizations(db_manager)
        
        print("\n=== 系统运行成功完成 ===")
        
    except Exception as e:
        print(f"系统运行过程中出现错误: {e}")
    finally:
        db_manager.close()

if __name__ == "__main__":
    main()

6. 部署与优化建议

性能优化策略

  1. 索引优化:为经常查询的字段创建索引,如用户ID、订单日期
  2. 批处理操作 :批量插入数据时使用​executemany()​方法
  3. 连接池:在高并发场景下实现连接池管理
  4. 查询优化:避免SELECT *,只选择需要的字段

安全最佳实践

  1. 参数化查询:始终使用参数化查询防止注入
  2. 数据验证:在应用层验证所有输入数据
  3. 权限控制:遵循最小权限原则配置数据库用户
  4. 敏感数据加密:对密码等敏感信息进行加密存储

扩展性考虑

  • 从SQLite迁移到PostgreSQL/MySQL时,只需修改连接字符串和部分SQL语法
  • 实现ORM(如SQLAlchemy)可提高代码可移植性
  • 添加缓存层(Redis)减少数据库访问频率

7. 执行说明与依赖安装

复制代码
# 安装所需依赖
pip install sqlite3 pandas matplotlib

# 运行应用
python database_skill.py

预期输出

  • 数据库文件​ecommerce.db​将在当前目录创建
  • 控制台显示详细的执行过程和结果
  • 生成​sales_report.png​图表文件,展示销售数据分析

此Skill完整实现了数据库从设计到可视化的全流程,代码可直接执行,包含错误处理、性能优化和安全实践,完全满足实际应用需求。通过这个教程,开发者可以掌握数据库核心技能并应用到真实项目中。

相关推荐
2301_812539671 小时前
Golang怎么实现网页爬虫抓取数据_Golang如何用colly框架快速构建爬虫采集程序【教程】
jvm·数据库·python
雪碧聊技术2 小时前
组合查询(union)
数据库·sql
杨云龙UP2 小时前
ODA运维实战:Oracle 19c YJXT PDB表空间在线扩容全过程_20260503
linux·运维·服务器·数据库·oracle
BENA ceic2 小时前
Spring 的三种注入方式?
java·数据库·spring
2401_895521342 小时前
MySQL中的count函数
数据库·mysql
雪碧聊技术2 小时前
IO流-07:缓冲流
数据库
.小小陈.2 小时前
MySQL 入门到实战:从基础概念到核心存储引擎
数据库·mysql
IT邦德2 小时前
Oracle 26ai 首发季度补丁 23.26.2.0.0 来了!单机版升级
数据库·oracle
yoyo_zzm2 小时前
Laravel10.x新特性全解析
数据库·mysql·架构