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 操作
适用场景 简单脚本、性能关键操作 中大型项目、团队开发
相关推荐
得意霄尽欢4 小时前
MySQL8.0 新特性随笔
数据库·mysql
assibe5 小时前
cmake基本语法结构
数据库·c++·cmake
孤狼程序员5 小时前
异常处理小妙招——1.别把“数据库黑话”抛给用户:论异常封装的重要性
java·数据库·mysql
java干货5 小时前
还在 @AfterEach 里手动 deleteAll()?你早就该试试这个测试数据清理 Starter 了
java·数据库·oracle
cui_win6 小时前
MySQL数据库恢复步骤(基于全量备份和binlog)
数据库·mysql
小钻风33667 小时前
Redis初阶学习
数据库·redis·缓存
郏国上7 小时前
如何把指定阿里云文件夹下的所有文件移动到另一个文件夹下,移动文件时把文件名称(不包括文件后缀)进行md5编码
数据库·阿里云·云计算
Akshsjsjenjd7 小时前
Ansible 核心功能:循环、过滤器、判断与错误处理全解析
java·数据库·ansible
kiwixing7 小时前
集群无法启动CRS-4124: Oracle High Availability Services startup failed
java·运维·数据库·mysql·postgresql·oracle