使用SQLAlchemy删表调用drop报AttributeError如何解决
问题背景
需求为删除数据库中名为New的数据表,初始编写的实现代码如下:
import pandas as pd import sqlalchemy sqlcon = sqlalchemy.create_engine('mssql://ABSECTDCS100TL/AdventureWorks?driver=ODBC+Driver+17+for+SQL+Server')3 df = pd.read_sql_query('SELECT * FROM DimReseller', sqlcon) df.to_sql('New',sqlcon,if_exists='append', index=False) sqlalchemy.schema.New.drop(bind=None, checkfirst=False)
运行代码后抛出如下错误:
AttributeError: module 'sqlalchemy.schema' has no attribute 'New'
错误原因
- 手误语法问题:
create_engine代码行末尾多输入了无意义的数字3,会直接触发语法报错 - 调用逻辑错误:
sqlalchemy.schema是SQLAlchemy的结构定义模块,不会自动为数据库中用户自定义命名的表生成模块级属性,直接访问sqlalchemy.schema.New本质是查找模块下不存在的属性,必然触发属性错误 - 参数传值错误:就算获取到了合法的表对象,
drop()方法传入bind=None时没有绑定有效数据库连接,也无法实际执行删表操作
正确实现方案
方案1:通过表反射调用ORM层drop方法
该方案是SQLAlchemy原生删表的标准写法,不需要手写SQL,跨数据库兼容性更好:
import pandas as pd import sqlalchemy from sqlalchemy import Table, MetaData # 修正原代码末尾多余的数字3 sqlcon = sqlalchemy.create_engine('mssql://ABSECTDCS100TL/AdventureWorks?driver=ODBC+Driver+17+for+SQL+Server') df = pd.read_sql_query('SELECT * FROM DimReseller', sqlcon) df.to_sql('New', sqlcon, if_exists='append', index=False) # 初始化元数据对象 metadata = MetaData() # 从数据库反射加载已存在的New表结构 new_tbl = Table('New', metadata, autoload_with=sqlcon) # 绑定连接执行删表,checkfirst=True会先校验表是否存在,避免表不存在时抛错 new_tbl.drop(bind=sqlcon, checkfirst=True)
方案2:直接执行原生SQL删表
该方案写法更简洁,适合不需要操作表对象的简单删表场景:
import pandas as pd import sqlalchemy sqlcon = sqlalchemy.create_engine('mssql://ABSECTDCS100TL/AdventureWorks?driver=ODBC+Driver+17+for+SQL+Server') df = pd.read_sql_query('SELECT * FROM DimReseller', sqlcon) df.to_sql('New', sqlcon, if_exists='append', index=False) # 建立连接执行原生删表语句,适配SQL Server的表存在判断语法 with sqlcon.connect() as conn: conn.execute(sqlalchemy.text("IF OBJECT_ID('New', 'U') IS NOT NULL DROP TABLE New;")) conn.commit()
内容的提问来源于stack exchange,提问作者user19143736
相关产品推荐
相关产品推荐

