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 操作
适用场景 简单脚本、性能关键操作 中大型项目、团队开发
相关推荐
lingggggaaaa10 小时前
小迪安全v2023学习笔记(一百三十四讲)—— Windows权限提升篇&数据库篇&MySQL&MSSQL&Oracle&自动化项目
java·数据库·windows·笔记·学习·安全·网络安全
小光学长10 小时前
基于Vue的保护动物信息管理系统r7zl6b88 (程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
前端·数据库·vue.js
一匹电信狗10 小时前
【MySQL】数据库的相关操作
linux·运维·服务器·数据库·mysql·ubuntu·小程序
TDengine (老段)12 小时前
连接 TDengine 遇到报错 “failed to connect to server, reason: Connection refused” 怎么办?
大数据·数据库·物联网·时序数据库·iot·tdengine·涛思数据
李慕婉学姐13 小时前
Springboot黄河文化科普网站5q37v(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·spring boot·后端
Cabbage_acmer13 小时前
MySQL期中考试突击!
数据库·mysql
Lu Yao_13 小时前
Redis 缓存
数据库·redis·缓存
小桥流水人家哇14 小时前
性能测试单场景测试时,是设置并发读多个文件,还是设置不同的用户读不同的文件?
数据库·性能测试技巧
表示这么伤脑筋的题我不会14 小时前
Oracle 21C 部署ogg踩过的坑
数据库·oracle
你不是我我14 小时前
【Java 开发日记】MySQL 与 Redis 如何保证双写一致性?
数据库·redis·缓存