使用SQLAlchemy执行UPDATE语句触发ResourceClosedError的原因
报错原因
这个报错和SQL语句本身的正确性无关,核心是你调用的pandas方法和SQL语句类型不匹配:
pd.read_sql()的设计用途是执行会返回行结果的查询类语句(以SELECT为主),方法内部会自动抓取数据库返回的结果集,封装成DataFrame返回。- 你传入的是
UPDATE语句,属于数据修改类DML语句,执行成功后只会返回受影响的行数,不会返回结果行,read_sql拿不到预期的行结果,就会触发ResourceClosedError。
你在SSMS中能正常执行是因为SSMS作为数据库客户端,对所有类型的SQL语句都兼容,执行后不管有没有结果集只会返回执行状态/影响行数,不会强制要求语句必须返回查询结果,和pd.read_sql的执行逻辑不一样。
修复方案
执行UPDATE/INSERT/DELETE这类不返回结果集的语句,不要用pd.read_sql,通过数据库连接的执行接口提交语句即可,注意执行修改操作后需要提交事务才能让修改生效:
from sqlalchemy import text update_sql = "UPDATE Players SET [Player Name] = REPLACE(REPLACE([Player Name], 'Christian', 'Chris') , 'Reece', 'John')" # 用上下文管理器自动处理事务提交/回滚 with sqlcon.begin() as conn: conn.execute(text(update_sql))
如果你执行完更新操作后,需要把更新后的表数据读取为DataFrame,单独写SELECT查询语句再调用pd.read_sql即可:
# 先执行更新 with sqlcon.begin() as conn: conn.execute(text(update_sql)) # 再读取数据到DataFrame df = pd.read_sql("SELECT * FROM Players", sqlcon)
注意:如果你用的是原生pymysql、pyodbc这类驱动而非sqlalchemy作为连接引擎,执行逻辑类似:创建游标后调用
cursor.execute()执行更新语句,之后调用conn.commit()提交事务即可。
内容的提问来源于stack exchange,提问作者rapha123
相关产品推荐
相关产品推荐

