经过前两章的学习,我们已经成功创建了python_db数据库和users数据表。本章将重点讲解如何通过 Python 向数据表中插入数据,包括单条数据插入、批量数据插入,以及插入过程中的特殊场景处理,同时强调数据一致性的重要性。
3.1 数据插入的基础原理
在数据库操作中,数据插入是将新记录添加到数据表中的过程,就像在 Excel 表格中新增一行数据。MySQL 通过INSERT语句实现数据插入,而 Python 则通过数据库驱动将INSERT语句发送给 MySQL 服务器执行。
需要注意的是,MySQL 中默认开启了事务机制(后续章节会详细讲解),对于数据插入这类写操作,执行后需要通过commit()方法提交事务,否则数据只会存在于当前连接的临时缓存中,不会真正保存到数据表中。
3.2 单条数据插入
单条数据插入是最基础的插入场景,适用于每次只添加一条记录的需求,例如用户注册时将新用户信息写入users表。
3.2.1 单条插入的 SQL 语法
基础语法如下:
INSERT INTO 表名 (字段1, 字段2, ..., 字段n)
VALUES (值1, 值2, ..., 值n);
其中,字段列表可省略(需按数据表字段定义顺序传入所有字段的值),但为了代码可读性和避免字段顺序变更导致的错误,建议明确指定字段列表。
3.2.2 Python 实现单条数据插入
以下示例将向users表插入一条用户数据(姓名:张三,年龄:25,邮箱:zhangsan@example.com,注册日期:2025-08-22):
import mysql.connector
from mysql.connector import Error
from datetime import date # 用于处理日期类型数据
def insert_single_data():
connection = None
try:
connection = mysql.connector.connect(
host='localhost',
user='root',
password='your_password',
database='python_db'
)
if connection.is_connected():
cursor = connection.cursor()
# 1. 定义插入SQL语句(明确指定字段列表)
insert_query = """
INSERT INTO users (name, age, email, register_date)
VALUES (%s, %s, %s, %s)
"""
# 2. 定义插入的数据(注意:日期类型可直接传入Python的date对象)
user_data = ("张三", 25, "zhangsan@example.com", date(2025, 8, 22))
# 3. 执行插入操作
cursor.execute(insert_query, user_data)
# 4. 提交事务(关键步骤,否则数据不生效)
connection.commit()
print(f"单条数据插入成功,新增记录ID:{cursor.lastrowid}")
# cursor.lastrowid 可获取刚插入记录的自增主键(id)值
except Error as e:
print(f"单条数据插入出错:{e}")
# 若插入失败,回滚事务(避免事务残留)
if connection:
connection.rollback()
finally:
if connection.is_connected():
cursor.close()
connection.close()
print("MySQL连接已关闭")
if __name__ == "__main__":
insert_single_data()
3.2.3 代码解析
- 参数化查询:示例中使用%s作为占位符,而非直接拼接字符串,这能有效避免SQL 注入攻击(一种常见的数据库安全风险),同时无需手动处理数据类型转换(如日期、字符串中的特殊字符)。
- 事务提交:connection.commit()是核心步骤,只有执行该方法,插入的数据才会被永久保存到数据库。
- 错误处理:except块中捕获异常并执行connection.rollback(),确保插入失败时撤销当前事务的所有操作,维持数据一致性。
3.3 批量数据插入
当需要一次性插入多条记录(如批量导入用户数据、批量备份数据)时,批量插入比多次执行单条插入更高效,能显著减少 Python 与 MySQL 服务器的通信次数,提升操作速度。
3.3.1 批量插入的 SQL 语法
批量插入只需在VALUES后跟上多组值,用逗号分隔:
INSERT INTO 表名 (字段1, 字段2, ..., 字段n)
VALUES (值1-1, 值1-2, ..., 值1-n),
(值2-1, 值2-2, ..., 值2-n),
...
(值m-1, 值m-2, ..., 值m-n);
3.3.2 Python 实现批量数据插入
以下示例将一次性向users表插入 3 条用户数据:
import mysql.connector
from mysql.connector import Error
from datetime import date
def insert_batch_data():
connection = None
try:
connection = mysql.connector.connect(
host='localhost',
user='root',
password='your_password',
database='python_db'
)
if connection.is_connected():
cursor = connection.cursor()
# 1. 定义批量插入SQL语句
insert_query = """
INSERT INTO users (name, age, email, register_date)
VALUES (%s, %s, %s, %s)
"""
# 2. 定义批量数据(列表嵌套元组,每个元组对应一条记录)
batch_user_data = [
("李四", 28, "lisi@example.com", date(2025, 8, 20)),
("王五", 23, "wangwu@example.com", date(2025, 8, 21)),
("赵六", 30, "zhaoliu@example.com", date(2025, 8, 22))
]
# 3. 执行批量插入(使用executemany()方法)
cursor.executemany(insert_query, batch_user_data)
# 4. 提交事务
connection.commit()
print(f"批量数据插入成功,共新增 {cursor.rowcount} 条记录")
# cursor.rowcount 可获取本次操作影响的记录数
except Error as e:
print(f"批量数据插入出错:{e}")
if connection:
connection.rollback()
finally:
if connection.is_connected():
cursor.close()
connection.close()
print("MySQL连接已关闭")
if __name__ == "__main__":
insert_batch_data()
3.3.3 批量插入 vs 单条循环插入
为了直观展示批量插入的优势,我们对比两种插入 1000 条数据的方式:
插入方式 | 核心方法 | 执行时间(示例) | 优势 |
批量插入 | executemany() | 0.12 秒 | 减少网络通信次数,效率高 |
单条循环插入 | execute () 循环 | 2.8 秒 | 逻辑简单,适用于少量数据 |
显然,数据量越大,批量插入的效率优势越明显。
3.4 特殊场景处理
在实际开发中,数据插入可能会遇到各种特殊情况,如字段值为空、数据重复、日期格式异常等,需要针对性处理。
3.4.1 插入空值(NULL)
如果数据表字段未设置NOT NULL约束,允许为空,可在 Python 中传入None表示空值。示例如下:
# 插入一条年龄为空的用户数据(age字段允许为空)
user_data_with_null = ("孙七", None, "sunqi@example.com", date(2025, 8, 23))
cursor.execute(insert_query, user_data_with_null)
connection.commit()
print("含空值数据插入成功")
3.4.2 处理数据重复(UNIQUE 约束冲突)
users表的email字段设置了UNIQUE约束,若插入已存在的邮箱,会触发1062 (23000)错误。可通过INSERT IGNORE或ON DUPLICATE KEY UPDATE解决:
- INSERT IGNORE:忽略重复数据,不报错也不插入
insert_ignore_query = """
INSERT IGNORE INTO users (name, age, email, register_date)
VALUES (%s, %s, %s, %s)
"""
# 插入已存在的邮箱(zhangsan@example.com),会被忽略
cursor.execute(insert_ignore_query, ("张三2", 26, "zhangsan@example.com", date(2025, 8, 24)))
connection.commit()
print("若数据重复则已忽略,无报错")
- ON DUPLICATE KEY UPDATE:若数据重复,更新已有记录的指定字段
insert_update_query = """
INSERT INTO users (name, age, email, register_date)
VALUES (%s, %s, %s, %s)
ON DUPLICATE KEY UPDATE name = %s, age = %s, register_date = %s
"""
# 插入已存在的邮箱,若重复则更新姓名、年龄和注册日期
user_data_update = ("张三更新", 27, "zhangsan@example.com", date(2025, 8, 24),
"张三更新", 27, date(2025, 8, 24)) # 后三个参数对应UPDATE的字段值
cursor.execute(insert_update_query, user_data_update)
connection.commit()
print("若数据重复则已更新,无报错")
3.4.3 日期类型数据处理
除了传入date对象,也可传入符合DATE格式(YYYY-MM-DD)的字符串,MySQL 会自动转换为日期类型。但推荐使用date对象,避免字符串格式错误:
# 方式1:传入date对象(推荐)
date_obj = date(2025, 8, 25)
# 方式2:传入符合格式的字符串
date_str = "2025-08-25"
# 两种方式均可正常插入
3.5 插入结果验证
插入数据后,我们可以通过查询操作验证数据是否成功写入,这也是开发中常用的调试手段。以下示例在插入后查询users表的所有数据:
def insert_and_verify():
connection = None
try:
connection = mysql.connector.connect(
host='localhost',
user='root',
password='your_password',
database='python_db'
)
if connection.is_connected():
cursor = connection.cursor()
# 1. 插入一条数据
insert_query = "INSERT INTO users (name, age, email, register_date) VALUES (%s, %s, %s, %s)"
cursor.execute(insert_query, ("周八", 29, "zhouba@example.com", date(2025, 8, 25)))
connection.commit()
# 2. 查询所有数据验证
select_query = "SELECT * FROM users"
cursor.execute(select_query)
all_users = cursor.fetchall() # 获取所有查询结果
print("插入后users表所有数据:")
# 打印字段名(增强可读性)
field_names = [i[0] for i in cursor.description]
print("\t".join(field_names))
# 打印每条记录
for user in all_users:
print("\t".join(map(str, user)))
except Error as e:
print(f"操作出错:{e}")
if connection:
connection.rollback()
finally:
if connection.is_connected():
cursor.close()
connection.close()
if __name__ == "__main__":
insert_and_verify()
运行后会输出类似以下结果(包含字段名和所有用户记录):
插入后users表所有数据:
id name age email register_date
1 张三 25 zhangsan@example.com 2025-08-22
2 李四 28 lisi@example.com 2025-08-20
3 王五 23 wangwu@example.com 2025-08-21
4 赵六 30 zhaoliu@example.com 2025-08-22
5 孙七 None sunqi@example.com 2025-08-23
6 张三更新 27 zhangsan@example.com 2025-08-24
7 周八 29 zhouba@example.com 2025-08-25
3.6 本章小结
本章我们系统学习了数据插入的核心技能:
- 单条数据插入的实现方法,理解参数化查询和事务提交的重要性
- 批量数据插入的优势与实现,掌握executemany()方法的使用
- 特殊场景处理,包括空值插入、重复数据处理、日期类型处理
- 插入结果验证的方法,通过查询确保数据正确写入
下一章将学习数据查询操作,包括基础查询、条件查询、排序查询和分页查询,帮助你从数据表中高效获取所需数据。