一、引言
工作中,对于重复性很高技术性不那么强的工作,通过更简单的方式去实现能减轻工作的压力提高自己的工作效率。对着Excel将里面的数据录入数据库也就是这样一个场景,50条摸摸鱼就录了,1000条呢?简化重复写入的操作,一定程度提高录入数据的准确率。以下就是使用Python将Excel数据写入数据库的简单案例。
二、涉及技术
- Excel数据读取
- 数据库连接
- 数据写入
- 事务处理
- 关联表处理
三、实现步骤
3.1 环境准备
mysql-connector-python
是 MySQL 官方提供的 Python 连接器和驱动。
pip install openpyxl mysql-connector-python
3.2 Excel数据
假设有一个Excel文件data.xlsx
(emmm…都不用假设了,就是汇总表格数据,需要的保留,不需要的删除,场景假设就是医生的诊断单),其中包含患者、医生和病因信息,需要分别写入到patients
、doctors
和causes
三个表中。
3.3 数据库结构
Patients
表:包含患者ID和姓名。DROP TABLE IF EXISTS `Patients`; CREATE TABLE `Patients` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 115 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
Doctors
表:包含医生ID和姓名。DROP TABLE IF EXISTS `Doctors`; CREATE TABLE `Doctors` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 92 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
Diagnoses
表:包含就诊记录ID、患者ID、医生ID和病情描述,其中患者ID和医生ID是外键。DROP TABLE IF EXISTS `Diagnoses`; CREATE TABLE `Diagnoses` ( `id` int(11) NOT NULL AUTO_INCREMENT, `patient_id` int(11) NOT NULL, `doctor_id` int(11) NOT NULL, `cause` text CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, PRIMARY KEY (`id`) USING BTREE, INDEX `patient_id`(`patient_id`) USING BTREE, INDEX `doctor_id`(`doctor_id`) USING BTREE, CONSTRAINT `Diagnoses_ibfk_1` FOREIGN KEY (`patient_id`) REFERENCES `Patients` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT, CONSTRAINT `Diagnoses_ibfk_2` FOREIGN KEY (`doctor_id`) REFERENCES `Doctors` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT ) ENGINE = InnoDB AUTO_INCREMENT = 57 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
3.4 Python代码实现
import mysql.connector
from openpyxl import load_workbook
# Excel文件路径
file_path = r'C:\Users\30735\Desktop\test.xlsx'
# 数据库配置
db_config = {
'user': 'username',
'password': 'password',
'host': 'localhost',
'database': 'database',
'raise_on_warnings': True
}
# 初始化连接和游标
try:
cnx = mysql.connector.connect(**db_config)
cursor = cnx.cursor()
except Error as e:
print(f"Error connecting to MySQL database: {e}")
exit(1)
# 准备三个表的SQL插入语句模板和查询语句模板
insert_patient_query = "INSERT INTO Patients (name) VALUES (%s)"
insert_doctor_query = "INSERT INTO Doctors (name) VALUES (%s)"
select_doctor_query = "SELECT * FROM Doctors WHERE name = %s"
insert_cause_query = "INSERT INTO Diagnoses (patient_id, doctor_id, cause) VALUES (%s, %s, %s)"
# 初始化字典以存储已插入患者和医生的ID
inserted_patients = {}
inserted_doctors = {}
try:
# 加载Excel工作簿
workbook = load_workbook(filename=file_path)
sheet = workbook.active
# 跳过第一行(表头),从第二行开始读取数据
for row in sheet.iter_rows(min_row=2, values_only=True):
patient_name = row[0]
doctor_name = row[1]
cause_description = row[2]
# 检查患者是否已经插入,如果没有则插入并获取ID
if patient_name not in inserted_patients:
cursor.execute(insert_patient_query, (patient_name,))
inserted_id = cursor.lastrowid
inserted_patients[patient_name] = inserted_id
patient_id = inserted_patients[patient_name]
# 检查医生是否已经插入
if doctor_name not in inserted_doctors:
# 检查医生是否已存在于数据库中
cursor.execute(select_doctor_query, (doctor_name,))
doctor = cursor.fetchone()
if doctor is None:
# 如果不存在,则插入医生并获取ID
cursor.execute(insert_doctor_query, (doctor_name,))
inserted_id = cursor.lastrowid
else:
# 如果已存在,则获取医生的ID
inserted_id = doctor[0] # 假设医生ID是查询结果的第一列
inserted_doctors[doctor_name] = inserted_id
doctor_id = inserted_doctors[doctor_name]
# 插入就诊记录,使用患者和医生的ID
cursor.execute(insert_cause_query, (patient_id, doctor_id, cause_description))
# 提交事务
cnx.commit()
except Error as e:
if cnx.is_connected():
cursor.close()
cnx.rollback() # 如果发生错误,回滚事务
print(f"Error inserting data into the database: {e}")
finally:
if cnx.is_connected():
cursor.close()
cnx.close()
print("Database connection closed.")
print("数据已成功写入数据库。")
四、延伸
使用mysql-connector-python
还可以查询MySQL数据库的很多其他信息。
数据库连接
使用用户名、密码、主机名和端口号建立到 MySQL 服务器的连接。
支持 SSL 连接,增强数据传输的安全性。
可以配置连接池,用于管理多个数据库连接,提高性能。
执行 SQL 查询
执行 SELECT 语句,从数据库中检索数据。
执行 INSERT、UPDATE 和 DELETE 语句,修改数据库中的数据。
执行 DDL(数据定义语言)语句,如 CREATE、ALTER 和 DROP,用于管理数据库结构。
事务管理
支持 ACID 属性的事务,确保数据的完整性和一致性。
提供提交(commit)和回滚(rollback)操作,以控制事务的边界和结果。
参数化查询
允许使用参数化查询,防止 SQL 注入攻击,提高查询的安全性。
参数化查询也使得代码更加清晰和易于维护。
结果集处理
将查询结果作为字典或元组的列表返回,方便 Python 代码处理。
提供游标(cursor)对象,用于遍历和访问查询结果。
错误处理
提供异常处理机制,当连接失败、查询错误或发生其他数据库相关问题时,可以捕获和处理这些异常。
批量操作
支持批量插入、更新或删除操作,提高数据处理效率。
存储过程和函数
调用 MySQL 中的存储过程和函数,执行预定义的数据库操作。
复制和负载均衡
支持连接到 MySQL 复制集,实现读写分离读取和负载均衡。
二进制数据处理
可以处理二进制数据,如 BLOB 和 TEXT 类型字段,允许在 Python 和 MySQL 之间传输二进制数据。
字符集和编码
支持设置连接和查询的字符集和编码,确保字符数据的正确传输和处理。
其他高级功能
提供对预处理语句的支持,用于优化重复执行的查询。
支持多种认证插件,如 Unix 套接字认证和 PAM 认证。
允许配置连接的超时时间和重试策略。