使用SQLAlchemy创建数据库表时如何参数化指定Schema名称?
问题描述
我在db_models.py模块中定义了如下数据库表:
from sqlalchemy import Column, String, Date from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class MyTable(Base): __tablename__ = 'mytable' __table_args__ = {'comment': 'test comment'} my_date = Column(Date, primary_key=True) my_word = Column(String(12)) class MyOtherTable(Base): __tablename__ = 'myothertable' __table_args__ = {'comment': 'test comment'} my_date = Column(Date, primary_key=True) my_song = Column(String(96))
随后在另一个模块中导入Base,想要将表创建在指定的test-schema Schema中,尝试了以下代码但未生效,表仍被创建在默认Schema:
from db_models import Base Base.metadata.schema = 'test-schema' Base.metadata.create_all(my_session.get_bind())
解决方案
方法1:表定义阶段指定Schema
如果Schema是固定的,可以直接在每个表的__table_args__中添加schema参数:
class MyTable(Base): __tablename__ = 'mytable' __table_args__ = {'comment': 'test comment', 'schema': 'test-schema'} my_date = Column(Date, primary_key=True) my_word = Column(String(12))
方法2:动态修改表的Schema(推荐用于动态指定场景)
不要直接修改Base.metadata.schema,而是对每个表对象使用with_options方法重新绑定Schema,再执行创建操作:
from db_models import Base, MyTable, MyOtherTable # 为每个表指定目标Schema target_tables = [ MyTable.__table__.with_options(schema='test-schema'), MyOtherTable.__table__.with_options(schema='test-schema') ] # 仅创建指定的带Schema的表 Base.metadata.create_all(my_session.get_bind(), tables=target_tables)
方法3:创建带Schema的新Metadata对象
基于原Base的表定义,生成一个绑定了目标Schema的新Metadata对象,再用它创建表:
from sqlalchemy import MetaData from db_models import Base # 初始化带Schema的新Metadata new_metadata = MetaData(schema='test-schema') # 将原Base中的表复制到新Metadata中 for table in Base.metadata.tables.values(): table.tometadata(new_metadata) # 使用新Metadata创建表 new_metadata.create_all(my_session.get_bind())
原因说明
直接修改Base.metadata.schema不生效的核心原因是:当表类继承Base时,表对象已经和初始的Base.metadata(此时Schema为None)完成绑定,后续修改Base.metadata.schema不会自动同步到已存在的表对象上,因此创建表时仍会使用默认Schema。
内容的提问来源于stack exchange,提问作者Sergey Zakharov
相关产品推荐
相关产品推荐

