Python 连接 SQLite 数据库:从建表到增删改查的完整演示项目
SQLite 是 Python 新手非常适合上手的数据库:它不需要单独安装数据库服务,数据直接保存在一个本地.db文件里。Python 标准库内置了sqlite3模块,所以只要安装了 Python,就可以直接操作 SQLite。
这篇文章用一个“小型学生信息管理”项目演示 Python 如何连接 SQLite 数据库,并完成建表、插入、查询、更新、删除等常见操作。
一、项目目标
我们要实现一个简单的学生表students,字段如下:
| 字段 | 类型 | 说明 |
|---|---|---|
| id | INTEGER | 主键,自增 |
| name | TEXT | 学生姓名 |
| age | INTEGER | 年龄 |
| major | TEXT | 专业 |
| score | REAL | 分数 |
最终项目支持这些功能:
- 自动创建数据库和数据表
- 新增学生信息
- 查询全部学生
- 根据 ID 查询单个学生
- 修改学生分数
- 删除学生记录
- 关闭数据库连接
二、准备环境
确认本机已经安装 Python:
python--version如果能看到类似下面的输出,就可以继续:
Python3.11.0sqlite3是 Python 标准库,不需要额外安装。
三、项目结构
新建一个目录,例如:
sqlite_crud_demo/ ├── app.py └── student.db其中:
app.py:我们编写的 Python 代码student.db:运行程序后自动生成的 SQLite 数据库文件
四、完整代码
在app.py中写入下面的代码:
importsqlite3frompathlibimportPath DB_PATH=Path(__file__).with_name("student.db")defget_connection():"""创建并返回数据库连接。"""conn=sqlite3.connect(DB_PATH)conn.row_factory=sqlite3.Rowreturnconndefcreate_table(conn):"""创建学生表。"""sql=""" CREATE TABLE IF NOT EXISTS students ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, age INTEGER NOT NULL, major TEXT NOT NULL, score REAL NOT NULL ); """conn.execute(sql)conn.commit()defadd_student(conn,name,age,major,score):"""新增学生。"""sql=""" INSERT INTO students (name, age, major, score) VALUES (?, ?, ?, ?); """cursor=conn.execute(sql,(name,age,major,score))conn.commit()returncursor.lastrowiddeflist_students(conn):"""查询全部学生。"""sql="SELECT id, name, age, major, score FROM students ORDER BY id;"returnconn.execute(sql).fetchall()defget_student_by_id(conn,student_id):"""根据 ID 查询学生。"""sql="SELECT id, name, age, major, score FROM students WHERE id = ?;"returnconn.execute(sql,(student_id,)).fetchone()defupdate_student_score(conn,student_id,new_score):"""修改学生分数。"""sql="UPDATE students SET score = ? WHERE id = ?;"cursor=conn.execute(sql,(new_score,student_id))conn.commit()returncursor.rowcountdefdelete_student(conn,student_id):"""删除学生。"""sql="DELETE FROM students WHERE id = ?;"cursor=conn.execute(sql,(student_id,))conn.commit()returncursor.rowcountdefprint_students(rows):"""格式化输出查询结果。"""ifnotrows:print("暂无学生数据")returnforrowinrows:print(f"id={row['id']}, "f"name={row['name']}, "f"age={row['age']}, "f"major={row['major']}, "f"score={row['score']}")defmain():withget_connection()asconn:create_table(conn)print("=== 新增学生 ===")alice_id=add_student(conn,"Alice",20,"Computer Science",92.5)bob_id=add_student(conn,"Bob",21,"Data Science",88.0)add_student(conn,"Cindy",19,"Software Engineering",95.0)print(f"Alice 的 ID 是:{alice_id}")print(f"Bob 的 ID 是:{bob_id}")print("\n=== 查询全部学生 ===")print_students(list_students(conn))print("\n=== 根据 ID 查询学生 ===")student=get_student_by_id(conn,alice_id)ifstudent:print(dict(student))print("\n=== 修改 Bob 的分数 ===")updated_count=update_student_score(conn,bob_id,90.5)print(f"更新记录数:{updated_count}")print("\n=== 修改后再次查询 ===")print_students(list_students(conn))print("\n=== 删除 Alice ===")deleted_count=delete_student(conn,alice_id)print(f"删除记录数:{deleted_count}")print("\n=== 删除后再次查询 ===")print_students(list_students(conn))if__name__=="__main__":main()运行程序:
python app.py第一次运行后,当前目录会自动生成student.db文件。
五、关键代码讲解
1. 连接 SQLite 数据库
conn=sqlite3.connect(DB_PATH)如果student.db已经存在,Python 会直接连接它;如果文件不存在,SQLite 会自动创建。
这里还设置了:
conn.row_factory=sqlite3.Row这样查询出来的每一行既可以像元组一样访问,也可以通过字段名访问:
row["name"]row["score"]这对新手更直观。
2. 创建数据表
CREATETABLEIFNOTEXISTSstudents(idINTEGERPRIMARYKEYAUTOINCREMENT,nameTEXTNOTNULL,ageINTEGERNOTNULL,majorTEXTNOTNULL,scoreREALNOTNULL);IF NOT EXISTS的作用是:如果表已经存在,就不会重复创建,也不会报错。
id INTEGER PRIMARY KEY AUTOINCREMENT表示id是主键,并且会自动递增。
3. 新增数据
sql=""" INSERT INTO students (name, age, major, score) VALUES (?, ?, ?, ?); """conn.execute(sql,(name,age,major,score))conn.commit()注意这里没有把变量直接拼接到 SQL 字符串里,而是使用了?占位符。
推荐写法:
conn.execute(sql,(name,age,major,score))不推荐写法:
sql=f"INSERT INTO students (name) VALUES ('{name}')"原因是字符串拼接容易引发 SQL 注入问题,也容易因为引号、特殊字符导致 SQL 执行失败。
4. 查询数据
查询全部学生:
rows=conn.execute("SELECT * FROM students").fetchall()查询单个学生:
row=conn.execute("SELECT * FROM students WHERE id = ?",(student_id,)).fetchone()这里(student_id,)后面的逗号不能省略。它表示这是一个只包含一个元素的元组。
5. 修改数据
sql="UPDATE students SET score = ? WHERE id = ?;"cursor=conn.execute(sql,(new_score,student_id))conn.commit()cursor.rowcount可以拿到受影响的行数:
returncursor.rowcount如果返回1,说明成功修改了一条记录;如果返回0,说明没有找到对应 ID 的学生。
6. 删除数据
sql="DELETE FROM students WHERE id = ?;"cursor=conn.execute(sql,(student_id,))conn.commit()删除操作也要记得调用commit(),否则修改不会真正保存到数据库文件。
六、commit 为什么重要
SQLite 的插入、修改、删除都属于写操作。执行写操作后,需要调用:
conn.commit()如果不提交事务,程序结束后数据可能不会保存。
常见规律:
SELECT查询:不需要commit()INSERT新增:需要commit()UPDATE修改:需要commit()DELETE删除:需要commit()
七、使用 with 自动管理连接
示例代码里使用了:
withget_connection()asconn:create_table(conn)这样可以让数据库连接的生命周期更清晰。代码块执行完成后,连接会被正确处理。对于小型脚本来说,这种写法简单、直观,也能减少忘记关闭连接的问题。
如果你不使用with,也可以这样写:
conn=get_connection()try:create_table(conn)finally:conn.close()八、常见错误总结
1. 忘记提交事务
conn.execute("INSERT INTO students ...")只执行 SQL 还不够,写操作后要加:
conn.commit()2. 单参数元组忘记逗号
错误写法:
conn.execute("SELECT * FROM students WHERE id = ?",(student_id))正确写法:
conn.execute("SELECT * FROM students WHERE id = ?",(student_id,))3. 直接拼接 SQL
错误写法:
sql=f"SELECT * FROM students WHERE name = '{name}'"正确写法:
sql="SELECT * FROM students WHERE name = ?"conn.execute(sql,(name,))九、可以继续扩展的方向
学会这个基础版本后,可以继续尝试:
- 增加命令行菜单,让用户输入选项操作数据库
- 增加异常处理,例如捕获数据库执行错误
- 增加更多字段,例如手机号、创建时间
- 把数据库操作封装成一个
StudentRepository类 - 使用 Flask 或 FastAPI 做一个简单的 Web 接口
十、总结
Python 操作 SQLite 的核心流程可以总结为:
连接数据库 -> 创建表 -> 执行 SQL -> 提交事务 -> 查询结果 -> 关闭连接最常用的几个方法是:
| 方法 | 作用 |
|---|---|
sqlite3.connect() | 连接数据库 |
conn.execute() | 执行 SQL |
conn.commit() | 提交事务 |
fetchone() | 查询一条记录 |
fetchall() | 查询多条记录 |
conn.close() | 关闭连接 |
SQLite 轻量、免安装、上手快,非常适合 Python 新手练习数据库的增删改查。掌握本文这个小项目后,再去学习 MySQL、PostgreSQL 或 ORM 框架,会更容易理解数据库操作的底层逻辑。