上一章我们把 SQLite 的定位讲清楚了。
你已经知道,它是最适合新手入门的数据库之一。 它足够轻,足够真实,而且和 Python 结合得非常顺。
那接下来最自然的一步,就是进入真正的实操:
怎么让 Python 连上数据库 怎么在 Python 里执行 SQL 怎么把“数据库这回事”从概念,真正变成你手里的代码能力
这一章特别关键。
因为很多人学数据库,卡住的不是“数据库为什么重要”。 而是到了真正写代码时,脑子会突然空一下:
连接数据库是不是很复杂 SQL 是写在什么地方 Python 和 SQL 到底谁在干什么 为什么有时候执行完了,数据没保存 为什么查出来的结果长得像元组
这些问题,一旦这一章理顺了,后面增删改查就会顺很多。
所以这一章的目标非常明确:
让你第一次真正用 Python 连上一个 SQLite 数据库,并执行最基础的 SQL 语句。
一、先搞清楚一件事:Python 不是数据库,SQL 也不是 Python
这是最先要建立的认知。
很多初学者一接触数据库代码,最容易混的一件事就是:
我现在到底是在写 Python,还是在写数据库语言
答案是:
你两种都在用,但它们分工不同。
Python 负责控制流程。 比如连接数据库、调用方法、接收结果、打印输出、做判断、写循环。
SQL 负责表达你想对数据库做什么。 比如建表、插入、查询、更新、删除。
你可以把它理解成这样:
Python 是总指挥。 SQL 是对数据库发出的具体指令。
比如下面这种写法:
cursor.execute("SELECT * FROM users")
这里:
cursor.execute(...) 是 Python 在调用方法。 引号里的 "SELECT * FROM users" 是 SQL 语句。
这一步非常关键。
因为后面你越来越多地会看到“Python 包着 SQL”的写法。 如果你不先分清谁负责流程、谁负责数据操作,很容易越学越乱。
二、Python 里操作 SQLite,最常用的是 sqlite3 模块
这一点非常舒服。
因为 sqlite3 是 Python 标准库的一部分。 很多情况下,你不需要额外安装任何第三方库,就能直接开始用。Python 官方文档明确说明,sqlite3 模块提供了一个符合 DB-API 2.0 的接口,用来访问 SQLite 数据库。
最基础的导入方式就是:
import sqlite3
这一步看起来很普通,但意义很大。
因为从这一刻开始,你已经不是在“讨论数据库”。 而是在真正准备让 Python 去操作数据库了。
三、第一步永远是先连接数据库
无论你后面是建表、插入数据、查数据,第一步都得先连上数据库。
SQLite 的连接方式非常直接:
import sqlite3conn = sqlite3.connect("demo.db")print(conn)
这里的 "demo.db" 就是数据库文件名。
如果这个文件已经存在,Python 会连接到它。 如果这个文件还不存在,SQLite 通常会帮你创建一个新的数据库文件。Python 官方文档对 sqlite3.connect(database) 的说明也是这样:它会打开一个 SQLite 数据库文件;如果文件不存在,就会创建它。
这个体验真的特别适合新手。
因为你第一次连数据库,不需要先启动服务,不需要先建账号,不需要先去管理台点一堆按钮。 你直接连一个文件就行。
这会让你非常直观地感受到:
原来数据库操作没有想象中那么玄。
四、连接对象 conn 到底是什么
这个变量你后面会一直见到。
例如:
conn = sqlite3.connect("demo.db")
这里的 conn 是 connection 的缩写,也就是连接对象。
你可以把它理解成:
Python 程序和数据库之间的一条连接通道。
后面很多动作,都会围绕它展开。
比如:
创建游标 提交事务 关闭连接
所以 conn 不是数据库本身。 它更像是你当前程序和这个数据库建立起来的一次会话连接。
这个理解特别重要。
因为你后面会发现,一个数据库文件可以被多次连接。 而每一次连接,本质上都是一个独立的连接对象。
五、连上数据库之后,第二步通常不是立刻写 SQL,而是先拿到游标
这是数据库代码里最常见、也是最容易让新手发懵的一个对象:cursor,也就是游标。
写法通常是:
cursor = conn.cursor()print(cursor)
很多人第一次看到这里,都会问:
游标到底是什么,为什么不能直接 conn.execute(...)
先说结论:
有些时候你确实可以直接在连接对象上执行 SQL。 但在教学和日常代码里,更常见、也更清楚的方式,还是先拿到游标。
游标你可以先简单理解成:
一个专门用来执行 SQL、并拿结果回来的操作手柄。
或者说得更接地气一点:
conn 像数据库连接这条通道。cursor 像你真正用来发指令、取结果的那个操作窗口。
Python 官方文档对 Connection.cursor() 的说明也是:它会创建并返回一个游标对象,用于执行 SQL 语句。
所以现在先别把游标想太神秘。 你只要记住一句最够用的话:
数据库连接之后,很多 SQL 操作通常都通过游标来执行。
六、最小数据库操作流程,先记这四步
到了这里,你可以先把最基础的 SQLite 操作流程记成四步:
连接数据库 创建游标 执行 SQL 关闭连接
最小版本长这样:
import sqlite3conn = sqlite3.connect("demo.db")cursor = conn.cursor()cursor.execute("SELECT 1")conn.close()
虽然这段代码没干什么有业务意义的事,但它已经把数据库操作的骨架搭起来了。
你后面做的所有表操作、数据操作,基本都绕不开这条主线。
七、真正的关键动作,是 execute
数据库代码里最常出现的方法之一,就是 execute()。
比如:
cursor.execute("CREATE TABLE users (id INTEGER, name TEXT)")
或者:
cursor.execute("SELECT * FROM users")
execute() 的作用很直接:
把一条 SQL 语句交给数据库去执行。
注意,这里有两个层面。
外面是 Python 方法调用。 里面是字符串形式的 SQL。
所以每次看到:
cursor.execute("某条 SQL")
你都可以在脑子里翻译成:
Python 正在让数据库执行这条 SQL 指令。
这一步理解透了,后面你看数据库代码就不会觉得别扭了。
八、先做第一件真正有意义的事:建表
数据库里最基本的对象之一就是表。
所以你第一次真正操作数据库,最自然的动作通常是建表。
例如我们建一个用户表:
import sqlite3conn = sqlite3.connect("demo.db")cursor = conn.cursor()cursor.execute("""CREATE TABLE users ( id INTEGER, name TEXT, age INTEGER)""")conn.close()
这段代码特别值得你慢慢拆开看。
CREATE TABLE users 表示创建一张叫 users 的表。 括号里定义了这张表有哪些字段。id INTEGER 表示 id 字段是整数。name TEXT 表示 name 字段是文本。age INTEGER 表示 age 字段是整数。
也就是说,从这里开始,你已经不再是随手往列表里塞字典了。 你开始认真定义数据结构了。
这正是数据库思维真正开始落地的地方。
九、为什么建表这一步特别重要
因为它意味着你在先定义数据规则,再存数据。
这和很多初学者平时写 Python 的习惯很不一样。
平时写列表、字典时,数据结构往往很随意:
user1 = {"name": "张三", "age": 18}user2 = {"name": "李四", "phone": "13800000000"}
字段能不一样,类型也能随便飘。
但数据库不是这样。
你在建表时就要先说清楚:
这张表有哪些字段 每个字段是什么类型 以后每条记录大体长什么样
这会逼着你开始认真设计数据,而不是临时乱塞。 这其实是从“写脚本”走向“做系统”的一个非常重要的转变。
十、建表之后,为什么很多人会踩第一个坑:明明执行了,表却没保存
这是一个必须提前讲清楚的点。
在 SQLite 里,像建表、插入、更新、删除这类会改变数据库内容的操作,通常在执行之后还需要提交,才能真正写入数据库。Python 官方文档说明,Connection.commit() 用于提交当前事务;如果不提交,修改可能不会真正保存。
也就是说,更稳的写法应该是:
import sqlite3conn = sqlite3.connect("demo.db")cursor = conn.cursor()cursor.execute("""CREATE TABLE users ( id INTEGER, name TEXT, age INTEGER)""")conn.commit()conn.close()
这里的 commit() 特别重要。
你可以先把它理解成:
把前面的修改正式落盘、正式确认保存。
这一步是很多新手最容易忽略的。 结果就是代码跑完了,看起来没报错,但数据库里什么也没有。
所以从现在开始,你要建立一个很实用的习惯:
凡是会改数据库内容的操作,做完都要想一句: 我是不是该 commit() 了
十一、什么时候需要 commit,什么时候不一定需要
先给你一个非常够用的判断法。
如果是“修改型”操作,通常要记得提交。 比如:
建表 插入 更新 删除
如果只是纯查询,一般不需要提交。 比如:
SELECT ...
因为查询只是读,不会改数据库内容。
所以你现在可以先记成:
改数据,要提交。 查数据,通常不用提交。
这是一个特别实用的入门规则。
后面你学事务时,会更系统地理解这件事。 但当前阶段,这样记已经非常好用了。
十二、查表结构,最简单的办法之一:直接查 sqlite_master
这算是一个很实用的小干货。
很多人第一次建完表,会想确认:
表到底建成功没有 数据库里现在到底有哪些表
SQLite 里有一个内部表叫 sqlite_master,可以用来查看数据库对象。
例如:
import sqlite3conn = sqlite3.connect("demo.db")cursor = conn.cursor()cursor.execute("SELECT name FROM sqlite_master WHERE type='table'")tables = cursor.fetchall()print(tables)conn.close()
这段代码会把当前数据库里的表名查出来。
它特别适合初学阶段做验证。
因为很多时候,你不是 SQL 写错了,而是你不确定到底有没有真的建成功。 这时与其猜,不如直接查一下。
十三、查询结果为什么看起来像一堆元组
再看刚才那段代码:
tables = cursor.fetchall()print(tables)
很多新手第一次看到输出会愣一下,可能长这样:
[('users',)]
为什么是这样。
因为数据库查询返回的结果,默认通常是一行一行的记录。 而每一行记录,会以元组形式表示。
所以:
('users',)
表示一行数据,而且这一行里只有一个字段,也就是表名。
如果你查询的是多个字段,比如:
SELECT id, name, age FROM users
那么一行结果可能就会长这样:
(1, '张三', 18)
这不是 SQLite 故意刁难你。 而是数据库结果本来就很适合按“记录”来返回。
所以你现在一定要先适应这件事:
查询出来的结果,不一定是字典。 默认很多时候是元组构成的列表。
这个感觉要早点建立,不然后面你会一直觉得输出怪怪的。
十四、fetchall、fetchone 到底是什么
这两个方法你很快就会反复见到。
当你执行完一条查询语句后,可以通过游标把结果取出来。
例如:
cursor.execute("SELECT name FROM sqlite_master WHERE type='table'")rows = cursor.fetchall()print(rows)
fetchall() 的意思是:
把当前查询结果的所有行,一次性全部取出来。
而 fetchone() 则是:
只取一行。
例如:
cursor.execute("SELECT name FROM sqlite_master WHERE type='table'")row = cursor.fetchone()print(row)
这两个方法以后特别高频。
你可以先这样记:
查一条,用 fetchone()查多条,用 fetchall()
当然,真实情况有时会更灵活,但入门阶段先这样理解最实用。
十五、为什么“连接、游标、执行、提交、取结果、关闭”是数据库最基础的操作节奏
因为后面你几乎所有数据库代码,都会围绕这个节奏展开。
比如你以后插入数据:
连接 游标 执行 INSERT 提交 关闭
你以后查询数据:
连接 游标 执行 SELECT 取结果 关闭
你以后更新数据:
连接 游标 执行 UPDATE 提交 关闭
所以这一章表面上只是入门。 但它其实是在给你建立数据库代码的节奏感。
你只要把这个节奏练熟,后面学增删改查时,脑子里就不会乱。
十六、一个完整的最小演示:从连接到查询
现在我们把前面讲的内容串成一个更完整的小例子。
import sqlite3conn = sqlite3.connect("demo.db")cursor = conn.cursor()cursor.execute("""CREATE TABLE users ( id INTEGER, name TEXT, age INTEGER)""")conn.commit()cursor.execute("SELECT name FROM sqlite_master WHERE type='table'")tables = cursor.fetchall()print("当前数据库中的表:", tables)conn.close()
这段代码做了几件特别明确的事:
连接数据库 创建表 提交保存 查询表是否存在 打印结果 关闭连接
它虽然还没插入数据,但已经足够让你第一次完整感受到:
原来 Python 操作数据库,真的是一套非常具体、非常可控的流程。
十七、实战里更稳一点的写法:建表时最好加 IF NOT EXISTS
这是个非常实用的干货。
如果你每次运行程序都写:
CREATE TABLE users (...)
那第一次可能成功。 第二次再运行时,很可能就会报错,因为这张表已经存在了。
更稳妥的写法通常是:
CREATE TABLE IF NOT EXISTS users ( id INTEGER, name TEXT, age INTEGER)
完整代码例如:
import sqlite3conn = sqlite3.connect("demo.db")cursor = conn.cursor()cursor.execute("""CREATE TABLE IF NOT EXISTS users ( id INTEGER, name TEXT, age INTEGER)""")conn.commit()conn.close()
这样即使表已经存在,再运行一次也不会轻易报错。
这类写法非常像真实项目代码。 因为真实项目最怕的不是第一次运行成功。 而是第二次、第三次运行就挂。
所以这类“更稳一点”的小习惯,特别值得早点养成。
十八、关闭连接为什么不能总是忘
有些新手写数据库代码时,连上了就一直不关。 程序短的时候也许没立刻出问题,但这不是好习惯。
conn.close()
这一步的意义是:
告诉程序,这次数据库操作结束了,连接可以释放了。
养成这个习惯特别重要。 因为数据库连接本身是资源。 不是说能连上就永远挂着不管。
尤其你后面做项目、做循环、做批量操作时,如果总是不认真关闭连接,问题会越来越多。
所以你现在就把它当作一个完整流程的最后一步:
做完了,就收尾。
这和你写文件时记得 close() 或者用 with open(...) 是一个思路。
十九、初学者在这一章最容易踩的坑
第一个坑,是连上数据库之后,不知道游标是干嘛的。
结果看到 cursor() 就开始慌。 你现在应该已经清楚了,游标本质上就是执行 SQL 和取结果的主要操作对象。
第二个坑,是忘了 commit()。
尤其是建表、插入、更新、删除之后,代码没报错,但结果没保存,这通常就是典型原因。
第三个坑,是把查询结果当成字典看。
结果看到元组列表就觉得很怪。 其实这是默认返回形式,后面你会慢慢习惯,也可以再学更方便的结果格式。
第四个坑,是每次运行都重复建表,但没加 IF NOT EXISTS。
第五个坑,是程序结束前忘了关闭连接。
这些坑都不高深,但几乎每个初学者都会碰到。 早点知道,会省很多调试时间。
二十、这一章真正要带走的,不是一段代码,而是一套数据库操作骨架
到这里,你最该真正带走的是这套最小骨架:
先连接数据库。 再创建游标。 然后通过 execute() 执行 SQL。 如果有修改,就记得 commit()。 如果有查询,就用 fetchone() 或 fetchall() 取结果。 最后关闭连接。
这套节奏非常重要。
因为后面你学插入、查询、更新、删除、建多张表,几乎都只是往这套骨架上继续加内容。
所以这一章你不要只把它看成“第一次连 SQLite”。 它其实是在帮你建立:
Python 操作数据库时最基础的手感和流程感。
本章小结
SQLite 是最适合新手入门的数据库之一,而 Python 通过标准库里的 sqlite3 模块,就可以直接操作它。Python 官方文档将 sqlite3 描述为一个 DB-API 2.0 接口模块,用于访问 SQLite 数据库。
这一章你最重要的收获,应该是把最基础的数据库操作链路真正理顺:
sqlite3.connect() 用来连接数据库文件;如果文件不存在,通常会自动创建。conn.cursor() 用来创建游标,后续很多 SQL 执行都通过游标完成。cursor.execute() 用来执行 SQL。conn.commit() 用来提交修改型操作,让建表、插入、更新、删除真正保存。fetchone() 和 fetchall() 用来取查询结果。conn.close() 用来关闭连接。
当你真正把这套最小流程走顺之后,数据库这件事就不再只是一个抽象概念,而会开始变成你手里真的能用起来的开发工具。