Python操作数据库的核心思路是建立连接、获取游标、执行SQL、处理结果、提交事务和关闭连接。该流程适用于SQLite、MySQL和PostgreSQL,遵循DB-API 2.0规范,接口一致,仅连接参数和库不同。SQLite轻量,适合本地开发;MySQL广泛用于Web应用;PostgreSQL功能强大,适合复杂业务。安全性方面需使用参数化查询防SQL注入,验证输入,遵循最小权限原则,并妥善处理错误。连接池可提升高并发下的性能。

Python操作数据库的核心思路其实很简单:建立连接、获取游标、执行SQL语句、处理结果、提交或回滚事务,最后关闭连接。无论你是用SQLite、MySQL还是PostgreSQL,这一套流程都大同小异,主要区别在于使用的Python库和连接参数。掌握了这套范式,就能灵活地与各种关系型数据库打交道。
在Python中,与关系型数据库交互通常遵循DB-API 2.0规范,这使得不同数据库的客户端库(如
sqlite3
PyMySQL
psycopg2
让我们一步步看看如何具体操作。
1. SQLite:轻量级本地数据库
立即学习“Python免费学习笔记(深入)”;
SQLite是Python标准库的一部分,无需额外安装。它以文件形式存储数据,非常适合本地开发、小型应用或作为配置存储。
import sqlite3
def operate_sqlite():
conn = None # 初始化连接对象
try:
# 连接到数据库文件,如果文件不存在则创建
conn = sqlite3.connect('my_database.db')
cursor = conn.cursor()
# 创建表
cursor.execute('''
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
age INTEGER
)
''')
print("表 'users' 创建或已存在。")
# 插入数据
# 注意使用参数化查询,防止SQL注入
cursor.execute("INSERT INTO users (name, age) VALUES (?, ?)", ('Alice', 30))
cursor.execute("INSERT INTO users (name, age) VALUES (?, ?)", ('Bob', 24))
print("数据插入成功。")
# 查询数据
cursor.execute("SELECT * FROM users WHERE age > ?", (25,))
print("\n查询结果 (年龄 > 25):")
for row in cursor.fetchall():
print(row)
# 更新数据
cursor.execute("UPDATE users SET age = ? WHERE name = ?", (31, 'Alice'))
print("数据更新成功。")
# 删除数据
cursor.execute("DELETE FROM users WHERE name = ?", ('Bob',))
print("数据删除成功。")
# 再次查询,确认更新和删除
cursor.execute("SELECT * FROM users")
print("\n当前所有用户:")
for row in cursor.fetchall():
print(row)
# 提交事务
conn.commit()
print("事务已提交。")
except sqlite3.Error as e:
print(f"数据库操作错误: {e}")
if conn:
conn.rollback() # 发生错误时回滚
print("事务已回滚。")
finally:
if conn:
conn.close() # 确保关闭连接
print("数据库连接已关闭。")
# operate_sqlite()2. MySQL:广泛使用的关系型数据库
操作MySQL需要安装第三方库,比如
PyMySQL
import pymysql
def operate_mysql():
conn = None
try:
# 连接到MySQL服务器
# 请替换为你的数据库信息
conn = pymysql.connect(
host='localhost',
user='your_mysql_user',
password='your_mysql_password',
database='your_database_name',
charset='utf8mb4',
cursorclass=pymysql.cursors.DictCursor # 返回字典形式的行
)
cursor = conn.cursor()
# 创建表
cursor.execute('''
CREATE TABLE IF NOT EXISTS products (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
price DECIMAL(10, 2)
)
''')
print("表 'products' 创建或已存在。")
# 插入数据
cursor.execute("INSERT INTO products (name, price) VALUES (%s, %s)", ('Laptop', 1200.50))
cursor.execute("INSERT INTO products (name, price) VALUES (%s, %s)", ('Mouse', 25.99))
print("数据插入成功。")
# 查询数据
cursor.execute("SELECT * FROM products WHERE price > %s", (100.00,))
print("\n查询结果 (价格 > 100):")
for row in cursor.fetchall():
print(row)
# 更新数据
cursor.execute("UPDATE products SET price = %s WHERE name = %s", (1250.00, 'Laptop'))
print("数据更新成功。")
# 删除数据
cursor.execute("DELETE FROM products WHERE name = %s", ('Mouse',))
print("数据删除成功。")
conn.commit()
print("事务已提交。")
except pymysql.Error as e:
print(f"数据库操作错误: {e}")
if conn:
conn.rollback()
print("事务已回滚。")
finally:
if conn:
conn.close()
print("数据库连接已关闭。")
# operate_mysql()3. PostgreSQL:功能强大的企业级数据库
操作PostgreSQL需要安装
psycopg2
import psycopg2
def operate_postgresql():
conn = None
try:
# 连接到PostgreSQL服务器
# 请替换为你的数据库信息
conn = psycopg2.connect(
host='localhost',
database='your_pg_database_name',
user='your_pg_user',
password='your_pg_password'
)
cursor = conn.cursor()
# 创建表
cursor.execute('''
CREATE TABLE IF NOT EXISTS orders (
id SERIAL PRIMARY KEY,
item_name VARCHAR(255) NOT NULL,
quantity INTEGER
)
''')
print("表 'orders' 创建或已存在。")
# 插入数据
cursor.execute("INSERT INTO orders (item_name, quantity) VALUES (%s, %s)", ('Keyboard', 5))
cursor.execute("INSERT INTO orders (item_name, quantity) VALUES (%s, %s)", ('Monitor', 2))
print("数据插入成功。")
# 查询数据
cursor.execute("SELECT * FROM orders WHERE quantity > %s", (3,))
print("\n查询结果 (数量 > 3):")
for row in cursor.fetchall():
print(row)
# 更新数据
cursor.execute("UPDATE orders SET quantity = %s WHERE item_name = %s", (6, 'Keyboard'))
print("数据更新成功。")
# 删除数据
cursor.execute("DELETE FROM orders WHERE item_name = %s", ('Monitor',))
print("数据删除成功。")
conn.commit()
print("事务已提交。")
except psycopg2.Error as e:
print(f"数据库操作错误: {e}")
if conn:
conn.rollback()
print("事务已回滚。")
finally:
if conn:
cursor.close()
conn.close()
print("数据库连接已关闭。")
# operate_postgresql()选择哪种数据库,这其实是个很经典的“看菜吃饭”问题,没有绝对的优劣,只有适不适合你的项目。我个人觉得,很多人在项目初期可能并不会深究,但随着项目发展,数据库的选择会越来越凸显其重要性。
SQLite:嵌入式与轻量级之选
MySQL:Web应用与通用业务的主力军
PostgreSQL:数据完整性与高级功能的王者
总结一下,如果只是快速启动一个小项目或做本地数据存储,SQLite轻巧方便;如果构建常见的Web应用,MySQL是久经考验的可靠选择;而如果你的项目对数据完整性、复杂查询有高要求,或者需要处理特殊数据类型,PostgreSQL则提供了更强大的功能集。
在数据库操作中,安全性永远是绕不过去的话题,尤其是SQL注入,那简直是悬在程序员头上的达摩克利斯之剑。我见过太多因为忽视安全导致数据泄露的案例,所以这块内容我认为是重中之重。
1. 坚决使用参数化查询(Prepared Statements)
这是防御SQL注入最核心、最有效的手段,没有之一。它的原理很简单:将SQL语句和参数分开传递给数据库,数据库会先编译SQL模板,再将参数安全地绑定进去,确保参数不会被当作SQL代码的一部分执行。
错误示例(易受SQL注入):
# 假设 username 和 password 来自用户输入
username = "admin"
password = "' OR '1'='1" # 恶意输入
sql = f"SELECT * FROM users WHERE username = '{username}' AND password = '{password}'"
# 最终SQL可能变成:SELECT * FROM users WHERE username = 'admin' AND password = '' OR '1'='1'
# 导致无需密码即可登录
cursor.execute(sql)正确示例(参数化查询):
# SQLite
cursor.execute("SELECT * FROM users WHERE username = ? AND password = ?", (username, password))
# MySQL (PyMySQL)
cursor.execute("SELECT * FROM users WHERE username = %s AND password = %s", (username, password))
# PostgreSQL (psycopg2)
cursor.execute("SELECT * FROM users WHERE username = %s AND password = %s", (username, password))你会发现,不同数据库驱动的占位符可能不同(
?
%s
2. 严格的输入验证与数据清洗
虽然参数化查询能防SQL注入,但这并不意味着你可以放松对用户输入的警惕。在数据进入数据库之前,对所有用户输入进行验证和清洗是另一个重要的安全层。
数据类型验证: 确保用户输入的年龄是整数,邮箱是有效的格式,电话号码是数字等。
长度限制: 防止过长的输入导致数据库字段溢出或DoS攻击。
字符过滤: 移除或转义不必要的特殊字符,例如HTML标签(防止XSS攻击)。
业务逻辑验证: 确保输入符合你的业务规则,例如,一个商品的库存不能是负数。
def validate_age(age_str):
try:
age = int(age_str)
if 0 < age < 150: # 合理的年龄范围
return age
else:
raise ValueError("年龄不在合理范围。")
except ValueError:
raise ValueError("年龄必须是有效的数字。")
# 使用前先验证
try:
user_age = validate_age(request_data.get('age'))
# 之后再将 user_age 传给参数化查询
except ValueError as e:
print(f"输入验证失败: {e}")
# 返回错误给用户3. 最小权限原则(Principle of Least Privilege)
为不同的应用程序或服务创建专门的数据库用户,并只授予它们完成其任务所需的最小权限。
避免使用root
按需授权: 如果一个应用只需要读取数据,就只给它
SELECT
INSERT
UPDATE
DELETE
-- 创建一个只读用户 CREATE USER 'readonly_app'@'localhost' IDENTIFIED BY 'secure_password'; GRANT SELECT ON your_database.* TO 'readonly_app'@'localhost'; -- 创建一个读写用户 CREATE USER 'webapp_user'@'localhost' IDENTIFIED BY 'another_secure_password'; GRANT SELECT, INSERT, UPDATE, DELETE ON your_database.* TO 'webapp_user'@'localhost'; FLUSH PRIVILEGES;
4. 错误处理与日志记录
不要在生产环境中向用户暴露详细的数据库错误信息,这可能会泄露数据库结构、表名、字段名等敏感信息。
捕获异常: 使用
try...except
通用错误信息: 向用户显示友好的、通用的错误消息(例如:“操作失败,请稍后再试。”)。
详细日志: 将详细的错误信息记录到日志文件中,供开发人员和运维人员排查问题。
import logging
logging.basicConfig(level=logging.ERROR, filename='app_errors.log')
try:
# 数据库操作
pass
except SomeDatabaseError as e:
logging.error(f"数据库操作失败: {e}")
# 向用户返回一个通用错误消息
return {"error": "Internal server error, please try again later."}安全性是一个持续的过程,没有一劳永逸的解决方案。将这些实践融入你的开发流程,才能构建出更健壮、更值得信赖的应用程序。
在实际项目中,尤其是在处理高并发或复杂业务逻辑时,仅仅知道如何执行SQL语句是远远不够的。如何高效地管理数据库连接,以及确保数据操作的原子性和一致性,才是真正考验开发者功力的地方。这就像是开车,你知道怎么踩油门刹车,但要开得又快又稳,还得懂交通规则和车辆维护。
1. 高效管理数据库连接:连接池(Connection Pooling)
每次与数据库建立连接都需要消耗时间和系统资源,包括TCP握手、认证等。如果每次请求都建立新连接,然后关闭,在高并发场景下会造成巨大的性能开销。连接池就是解决这个问题的利器。
以上就是如何使用Python操作数据库(SQLite/MySQL/PostgreSQL)?的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号