conn.execute的用法详解

本文详细比较了conn.execute与rs.open的不同之处,介绍了它们在性能及灵活性方面的差异,并分享了一些实用的操作建议。

conn.execute、rs.open之间的差别,conn.execute、rs.open、command.execute方法用法大大不同

通常形成记录集可以使用

Set rs=conn.execute(SQL)

或直接

rs=CONN.execute(SQL)

Set rs=Server.CreateObject("ADODB.Recordset")
rs.open SQL,CONN,0,1 或 rs.open SQL,CONN

这种情况 通常open比上一个性能要好那么一丁点
( command对象更灵活,执行范围更广)

使用 CONN.execute 可以不用关闭直接执行下一个 set rs=conn.execute(SQL)
但性能速度会大打折扣!!

大约要慢 2~5倍!!(这是我在msSQL循环1000次亲自测试过的,不信你马上自己测试),所以执行下一个 rs=conn.execute之前!!一定要关闭掉!是个好习惯!

使用单一对象的rs rs.open在open下一个记录集之前,必需要求显示关闭,否则出错,速度在SQL,CONN,0,1的情况下可前者基本一样

所以我喜欢使用直设置一个 CreateObject("adodb.recordser"(在不需要多个记录集交错操作的情况下,多个也不碍是!)然后从头用到尾!!!

开门关门开门关门

最后一个 set rs=nothing 化上句号!

更主要是 open提供非常灵活的操作数据库元数据的非常多的属性!!
打开百宝箱,金光灿灿什么都看见!
有很多情况下是非得用open来做的!
而conn.execute 想黑布下换胶卷~~~偷偷摸摸~~非常单一!!!

比如:

 

你提供的 `execute` 方法用于执行写操作(如 `INSERT`、`UPDATE`、`DELETE`),但存在一些**关键问题**,尤其是在使用了 `DictCursor` 和缺乏异常处理方面。下面我们进行 **全面优化与重构**,使其更健壮、安全、可维护。 --- ### ❌ 原始代码的问题分析 ```python def execute(self, sql: str, params: tuple | None): with self.conn.cursor(cursor=pymysql.cursors.DictCursor) as cursor: cursor.execute(sql, params or ()) self.conn.commit() return cursor.rowcount ``` | 问题 | 说明 | |------|------| | 使用 `DictCursor` 执行写操作 | 浪费性能,`DictCursor` 是为查询设计的,会解析字段名,而写操作不需要 | | 没有异常处理 | 若 SQL 出错或连接中断,不会回滚事务,可能导致数据不一致 | | 直接使用 `self.conn` | 缺少连接状态管理,若连接断开、未初始化或超时将导致崩溃 | | 无返回值类型提示 | 不利于 IDE 提示和静态检查 | | 未记录日志 | 调试困难,无法追踪执行的 SQL 和参数 | --- ## ✅ 优化目标 - ✅ 使用合适的游标(默认 Cursor) - ✅ 添加异常捕获并自动回滚 - ✅ 封装连接获取逻辑(使用上下文管理器) - ✅ 添加日志输出 - ✅ 完善类型提示 - ✅ 返回受影响行数(保留原功能) --- ## ✅ 优化后的完整实现 ```python # database.py import pymysql from typing import Tuple, Optional, Any from contextlib import contextmanager import logging logger = logging.getLogger(__name__) class DatabaseError(Exception): """自定义数据库异常""" pass class Database: def __init__(self, host: str, port: int, user: str, password: str, database: str, charset: str = 'utf8mb4'): self.config = { 'host': host, 'port': port, 'user': user, 'password': password, 'database': database, 'charset': charset, 'autocommit': False } @contextmanager def get_connection(self): conn = None try: conn = pymysql.connect(**self.config) logger.info("✅ 成功建立数据库连接") yield conn except Exception as e: logger.error(f"❌ 连接数据库失败: {e}") raise DatabaseError(f"数据库连接错误: {e}") from e finally: if conn: conn.close() logger.info("🔌 数据库连接已关闭") def execute(self, sql: str, params: Optional[Tuple[Any, ...]] = None) -> int: """ 执行写操作 (INSERT/UPDATE/DELETE),返回影响的行数 :param sql: SQL 语句,支持 %s 占位符 :param params: 参数元组,防止 SQL 注入 :return: 受影响的行数 :raises: DatabaseError 如果执行失败 """ with self.get_connection() as conn: try: with conn.cursor() as cursor: # 使用默认 Cursor,更适合写操作 logger.debug(f"Executing SQL: {sql}, Params: {params}") cursor.execute(sql, params or ()) affected_rows = cursor.rowcount conn.commit() logger.info(f"✅ SQL 执行成功,影响 {affected_rows} 行") return affected_rows except Exception as e: conn.rollback() error_msg = f"SQL 执行失败: {e}, SQL: {sql}, Params: {params}" logger.error(error_msg) raise DatabaseError(error_msg) from e ``` --- ## ✅ 使用示例 ```python db = Database( host="localhost", port=3306, user="root", password="123456", database="test_db" ) # 插入数据 try: rows = db.execute( "INSERT INTO users (name, email) VALUES (%s, %s)", ("Alice", "alice@example.com") ) print(f"插入成功,影响 {rows} 行") except DatabaseError as e: print("执行失败:", e) # 更新数据 try: rows = db.execute( "UPDATE users SET email = %s WHERE name = %s", ("new_alice@example.com", "Alice") ) print(f"更新成功,影响 {rows} 行") except DatabaseError as e: print("更新失败:", e) ``` --- ## ✅ 关键改进点详解 ### 1. ✅ 使用默认 `Cursor` 而非 `DictCursor` - `DictCursor` 会把结果包装成字典 `{column: value}`,适用于 `SELECT`。 - 写操作不需要解析列名,用默认 `Cursor` 更高效。 > ✔️ 正确做法:仅在 `query()` 中使用 `DictCursor`;`execute()` 使用默认游标。 --- ### 2. ✅ 异常处理 + 自动回滚 ```python except Exception as e: conn.rollback() # 回滚事务 raise DatabaseError(...) from e ``` - 防止部分执行导致的数据不一致。 - 上层可以捕获 `DatabaseError` 统一处理。 --- ### 3. ✅ 连接封装:`get_connection()` - 使用 `@contextmanager` 管理连接生命周期。 - 自动关闭连接,避免资源泄漏。 - 支持重试、健康检查等扩展能力。 --- ### 4. ✅ 日志记录 - 记录 SQL、参数、执行结果、错误信息。 - 方便调试和审计。 --- ### 5. ✅ 类型提示完善 ```python def execute(self, sql: str, params: Optional[Tuple[Any, ...]] = None) -> int: ``` - 提高代码可读性和工具支持(如 PyCharm、mypy)。 --- ## ✅ 最佳实践建议 | 场景 | 推荐做法 | |------|----------| | `INSERT/UPDATE/DELETE` | 使用 `execute()` + 默认 `Cursor` | | `SELECT` 查询 | 使用 `query()` + `DictCursor` | | 多条 SQL 一起提交 | 手动控制事务(不要每条都 commit) | | 批量插入 | 使用 `executemany()` | | 高并发场景 | 使用连接池(如 `DBUtils.PooledDB`) | ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值