SQLite数据库

一、SQLite 简介

QLite 是一个轻量级、嵌入式、无服务器 的关系型数据库,适用于小型项目、移动应用、测试环境等场景。Python 内置 sqlite3 模块,无需安装即可使用。

特点:

  • 无需独立服务器,数据库存储在单一文件中

  • 支持标准 SQL 语法

  • 跨平台、高性能、易于集成

二、数据存储方式对比

方式 存储位置 是否持久化 适用场景
变量 内存 临时数据、程序运行时
文件 磁盘 JSON/CSV/TXT/Excel 等
数据库 磁盘 结构化数据、复杂查询

三、SQLite 操作方式

1、原生 SQL 语句操作(基础方式)

操作流程:

  1. 导入 sqlite3 模块

  2. 连接数据库:conn = sqlite3.connect('db_name.db')

  3. 创建游标:cur = conn.cursor()

  4. 执行 SQL 语句:cur.execute(sql)

  5. 提交事务:conn.commit()

  6. 关闭连接:conn.close()

常用 SQL 语句:

操作 SQL 示例
创建表 CREATE TABLE table_name (id INTEGER PRIMARY KEY, name TEXT NOT NULL);
删除表 DROP TABLE table_name;
插入数据 INSERT INTO table_name (name, age) VALUES (?, ?);
查询数据 SELECT * FROM table_name;
更新数据 UPDATE table_name SET age = 30 WHERE name = 'Alice';
删除数据 DELETE FROM table_name WHERE id = 1;
模糊查询 SELECT * FROM table_name WHERE name LIKE '%Alice%';

示例:

python 复制代码
import sqlite3

# 1. 连接到数据库(如果不存在则创建)
# 注意:连接对象是线程不安全的,每个线程应创建自己的连接。
conn = sqlite3.connect('example.db') # 数据库存储在 example.db 文件中
# 可以使用 ':memory:' 创建内存数据库,仅程序运行时存在
# conn = sqlite3.connect(':memory:')

# 2. 创建游标对象
# 游标是用于执行 SQL 命令和获取结果的主要对象
cursor = conn.cursor()

try:
    # 3. 执行 SQL 语句 - 创建表
    cursor.execute('''
        CREATE TABLE IF NOT EXISTS users (
            id INTEGER PRIMARY KEY AUTOINCREMENT, -- 自增主键
            username TEXT NOT NULL UNIQUE,        -- 用户名,不能重复
            email TEXT,                           -- 邮箱,可为空
            age INTEGER,                          -- 年龄
            created_at DATETIME DEFAULT CURRENT_TIMESTAMP -- 创建时间,自动设置
        )
    ''')

    # 4. 插入数据 - 安全的方式(防止SQL注入)
    # 使用 ? 作为占位符,参数以元组形式传入
    user_data = ('alice', 'alice@example.com', 25)
    cursor.execute('INSERT INTO users (username, email, age) VALUES (?, ?, ?)', user_data)
    
    # 插入多条数据
    users_list = [
        ('bob', 'bob@example.com', 30),
        ('charlie', 'charlie@example.com', 35),
        ('diana', None, 28)  # email 为 NULL
    ]
    cursor.executemany('INSERT INTO users (username, email, age) VALUES (?, ?, ?)', users_list)

    # 5. 查询数据
    # 查询所有数据
    cursor.execute('SELECT * FROM users')
    all_users = cursor.fetchall()  # 获取所有记录,返回列表元组
    print("All users:")
    for user in all_users:
        print(user)

    # 查询单条数据
    cursor.execute('SELECT * FROM users WHERE username = ?', ('alice',))
    alice = cursor.fetchone()  # 获取单条记录
    print(f"\nAlice's data: {alice}")

    # 6. 更新数据
    cursor.execute('UPDATE users SET age = ? WHERE username = ?', (26, 'alice'))
    print(f"Updated {cursor.rowcount} row(s)")

    # 7. 删除数据
    cursor.execute('DELETE FROM users WHERE username = ?', ('charlie',))
    print(f"Deleted {cursor.rowcount} row(s)")

    # 8. 提交事务 - 非常重要!
    # 确保所有的更改被永久保存到数据库
    conn.commit()
    print("Transaction committed successfully")

except sqlite3.Error as e:
    # 9. 如果出现错误,回滚事务
    print(f"Database error: {e}")
    conn.rollback()
finally:
    # 10. 关闭连接 - 释放资源
    cursor.close()
    conn.close()
    print("Database connection closed")

关键细节与注意事项

  1. SQL注入防护永远不要 使用字符串拼接的方式构造 SQL 语句(如 f"SELECT * FROM users WHERE name = '{user_input}'")。务必使用参数化查询(? 占位符)。

  2. 事务管理

    • conn.commit():提交当前事务,使更改永久化。

    • conn.rollback():回滚当前事务,撤销所有未提交的更改。

    • 对于写操作(INSERT, UPDATE, DELETE),必须在操作后调用 commit()

  3. 连接管理

    • 使用 with 语句可以自动管理连接的关闭:

      复制代码
      with sqlite3.connect('example.db') as conn:
          cursor = conn.cursor()
          # ... 操作数据库
      # 离开 with 块后连接自动关闭
  4. 结果获取方法

    • fetchone():获取下一行。

    • fetchall():获取所有行。

    • fetchmany(size):获取指定数量的行。

  5. 数据类型映射

    • SQLite 数据类型会自动映射到 Python 类型(TEXT→str, INTEGER→int, REAL→float, BLOB→bytes)。

2、ORM 操作(推荐用于项目开发)

操作流程:

1.安装依赖:

python 复制代码
pip install fastapi sqlalchemy uvicorn

2.导入模块:

python 复制代码
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import sessionmaker, declarative_base

3.创建引擎和会话:

python 复制代码
engine = create_engine("sqlite:///test.db")
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()

4.定义数据模型:

python 复制代码
class User(Base):
    __tablename__ = "users"
    id = Column(Integer, primary_key=True, index=True)
    name = Column(String, unique=True)
    age = Column(Integer)

5.创建表:

python 复制代码
Base.metadata.create_all(bind=engine)

6.使用会话进行 CRUD 操作

操作 方法示例
插入 db.add(user); db.commit()
查询全部 db.query(User).all()
按条件查 db.query(User).filter(User.name == "Alice").first()
更新 user.age = 25; db.commit()
删除 db.delete(user); db.commit()

示例:

python 复制代码
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import declarative_base, sessionmaker

# 1. 定义基类
Base = declarative_base()

# 2. 定义数据模型
class User(Base):
    __tablename__ = 'users'
    
    id = Column(Integer, primary_key=True, autoincrement=True)
    username = Column(String(50), unique=True, nullable=False)
    email = Column(String(100))
    age = Column(Integer)
    
    def __repr__(self):
        return f"<User(username='{self.username}')>"

# 3. 创建数据库引擎和会话工厂
engine = create_engine('sqlite:///simple_example.db')
SessionLocal = sessionmaker(bind=engine)

# 4. 创建表
Base.metadata.create_all(bind=engine)

# 5. 使用会话进行数据库操作
def main():
    # 创建会话
    db = SessionLocal()
    
    try:
        # 先清空表(简单示例中常用)
        db.query(User).delete()
        
        # 插入新数据
        user1 = User(username='alice', email='alice@example.com', age=25)
        user2 = User(username='bob', email='bob@example.com', age=30)
        
        db.add(user1)
        db.add(user2)
        
        # 提交插入操作
        db.commit()
        
        # 查询所有用户
        all_users = db.query(User).all()
        print("所有用户:", all_users)
        
        # 查询特定用户
        alice = db.query(User).filter(User.username == 'alice').first()
        print("Alice的信息:", alice)
        
        # 更新数据
        if alice:
            alice.age = 26
            db.commit()
            print("更新后的Alice年龄:", alice.age)
        
        # 删除数据
        bob = db.query(User).filter(User.username == 'bob').first()
        if bob:
            db.delete(bob)
            db.commit()
            print("已删除Bob用户")
        
        # 查看最终结果
        remaining_users = db.query(User).all()
        print("剩余用户:", remaining_users)
        
    except Exception as e:
        db.rollback()
        print(f"发生错误: {e}")
    finally:
        db.close()

if __name__ == "__main__":
    main()

关键细节与注意事项

  1. 会话生命周期

    • 会话(Session)相当于 SQLite 中的连接,但功能更强大。

    • 会话跟踪对象的更改,实现工作单元模式。

  2. 对象状态

    • Transient:对象存在,但不在会话中,未保存到数据库。

    • Pending:对象已添加到会话,但未刷新到数据库。

    • Persistent:对象已在数据库中,与会话关联。

    • Detached:对象曾在数据库中,但已与会话分离。

  3. 查询方法

    • all():返回所有结果的列表。

    • first():返回第一个结果,如果没有则返回 None。

    • one():返回一个结果,如果不是恰好一个则抛出异常。

    • count():返回结果数量。

  4. 关系映射

    • SQLAlchemy 支持定义表之间的关系(一对一、一对多、多对多)。

    • 使用 relationship() 定义关系,ForeignKey 定义外键。

  5. 性能优化

    • 使用 lazy='joined'lazy='subquery' 优化关联数据的加载。

    • 对于大量数据,使用 yield_per() 进行流式处理。

四、总结

特性 原生 SQL (sqlite3) ORM (SQLAlchemy)
学习曲线 需要熟悉 SQL 需要学习 ORM 概念
灵活性 非常高,可执行任意 SQL 较高,但复杂查询可能仍需 SQL
安全性 需手动防止 SQL 注入 自动防止 SQL 注入
可维护性 较低,SQL 与代码混合 较高,面向对象,代码清晰
开发效率 较低 较高,特别是 CRUD 操作
适用场景 简单脚本、性能关键操作 中大型项目、团队开发
相关推荐
whn197733 分钟前
批量获取oracle的AWR报告方法
数据库·oracle
小旺不正经1 小时前
数据库表实现账号池管理
数据库·后端·算法
sanx182 小时前
一站式电竞平台解决方案:数据、直播、源码,助力业务飞速启航
前端·数据库·apache·数据库开发·时序数据库
学IT的周星星2 小时前
《MyBatis变形记:当SQL遇上“智能管家“》
数据库·sql·mybatis
byte轻骑兵2 小时前
突破文档型数据库迁移困境:金仓多模方案破解电子证照系统国产化难题
数据库
xdpcxq10293 小时前
EF Core框架数据库连接管理
java·jvm·数据库
期待のcode4 小时前
MyBatis框架—延迟加载与多级缓存
java·数据库·后端·缓存·mybatis
老华带你飞4 小时前
小区服务|基于Java+vue的小区服务管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·论文·毕设·小区服务管理系统
柯南二号4 小时前
【Java后端】MyBatis 和 MyBatis-Plus (MP) 的区别
java·数据库·tomcat