悠悠楠杉
实战指南:Python中用PyMySQL操作MySQL数据库
一、为什么选择PyMySQL?
在Python生态中,MySQL操作主要有三种方案:
1. MySQL官方驱动(mysql-connector)
2. ORM工具(如SQLAlchemy)
3. 轻量级方案PyMySQL
PyMySQL凭借纯Python实现、兼容性好(支持Python 3.x)、API简洁等特点,成为开发者首选。尤其在需要快速原型开发或不想依赖C扩展的环境下表现优异。
二、环境准备
python
安装PyMySQL(建议使用虚拟环境)
pip install pymysql
同时需要确保:
- MySQL服务已启动(本地或远程)
- 拥有数据库账号(至少需SELECT权限)
- 目标数据库已创建
三、建立数据库连接
python
import pymysql
def createconnection():
try:
connection = pymysql.connect(
host='localhost', # 数据库服务器地址
user='yourusername', # 用户名
password='yourpwd', # 密码
database='testdb', # 数据库名
charset='utf8mb4', # 字符编码
cursorclass=pymysql.cursors.DictCursor # 返回字典格式结果
)
print("数据库连接成功")
return connection
except pymysql.MySQLError as e:
print(f"连接失败: {e}")
关键参数说明:
- cursorclass
:指定DictCursor
可让查询结果以字典形式返回
- autocommit
:默认False,建议手动控制事务
- port
:非默认3306端口时需要指定
四、CRUD操作实战
1. 数据查询(SELECT)
python
def query_data(connection):
with connection.cursor() as cursor:
sql = "SELECT * FROM users WHERE age > %s"
cursor.execute(sql, (18,))
results = cursor.fetchall()
for row in results:
print(f"ID: {row['id']}, 姓名: {row['name']}")
注意事项:
- 使用参数化查询(%s
占位符)防止SQL注入
- fetchone()
获取单条记录,fetchmany(size)
获取指定数量
2. 数据插入(INSERT)
python
def insert_data(connection):
try:
with connection.cursor() as cursor:
sql = "INSERT INTO users (name, age) VALUES (%s, %s)"
cursor.execute(sql, ('张三', 25))
connection.commit() # 必须显式提交
print("插入成功")
except:
connection.rollback()
print("插入失败")
3. 批量操作
python
data = [('李四', 30), ('王五', 22), ('赵六', 28)]
cursor.executemany("INSERT INTO users (name, age) VALUES (%s, %s)", data)
五、事务管理与异常处理
python
def transfermoney(conn, fromid, toid, amount):
try:
with conn.cursor() as cursor:
# 检查余额
cursor.execute("SELECT balance FROM accounts WHERE id=%s", (fromid,))
balance = cursor.fetchone()['balance']
if balance < amount:
raise ValueError("余额不足")
# 转账操作
cursor.execute("UPDATE accounts SET balance=balance-%s WHERE id=%s",
(amount, from_id))
cursor.execute("UPDATE accounts SET balance=balance+%s WHERE id=%s",
(amount, to_id))
conn.commit()
except Exception as e:
conn.rollback()
print(f"转账失败: {e}")
六、性能优化建议
- 连接池管理:使用
DBUtils
或SQLAlchemy
的连接池 - 批量操作:优先使用
executemany
而非循环单条插入 - 索引优化:确保查询字段有适当索引
- 适当断开:长时间不用的连接及时关闭
七、完整示例代码
python
import pymysql
from contextlib import contextmanager
@contextmanager
def db_connection():
conn = pymysql.connect(
host='localhost',
user='root',
password='secret',
database='demo'
)
try:
yield conn
finally:
conn.close()
使用示例
with db_connection() as conn:
with conn.cursor() as cursor:
cursor.execute("SELECT VERSION()")
print(f"MySQL版本: {cursor.fetchone()[0]}")