我在一个脚本中使用SA,我将使用它定期将mysql表的一个子集从“生产”副本“复制”到dev/test系统。我编写代码只是为了反映源表和meta.create_all(destination_engine)
。由于FKs的性质,我现在知道我需要在创建表时将use_alter=True
应用于表上的外键,这样我就不会遇到CircularDependencyErrors或其他问题。我需要假设我不知道有多少FK或他们的名字,直到我通过元数据。
我是SA新手,通常是Java程序员(如您所知:D)。我试着改变这个用法。开始迭代:
tablesd = smeta.tables.items()
for tname, t in tablesd:
for c in t.columns:
for fk in c.foreign_keys:
fk.use_alter = True
smeta.create_all(to_engine)
编辑:需要注意的是,create_all()不会像上面那样在设置use_alter属性之后抛出循环rdependencyerror。如果删除该代码,create_all()将不起作用。它只是似乎没有从创建中删除FKs。。。
这显然行不通。然后我阅读了SA文档中的Overriding Reflected Columns,示例如下:
mytable = Table('mytable', meta,
Column('id', Integer, primary_key=True), # override reflected 'id' to have primary key
Column('mydata', Unicode(50)), # override reflected 'mydata' to be Unicode, autoload=True)
我想单独反映每个表,然后在FK定义中添加
use_alter=True
是可行的,但我不能假定FK/列的名称和值或。我读了很多关于使用DeclarativeBase
来做这样的事情的文章,但我不确定这会如何工作。。。如何获取任意表列表,反映它们,然后重写它们各自外键上的use_alter选项?我是不是想错了?
最佳答案
答案就在问题的内部(想象一下…)。尽管每个ForeignKey
对象都有一个可以设置的use_alter
值,Constraints
也有一个可以设置的单独属性(我在API Documentation中找不到这个属性)。在通过PyDev的调试器运行它之后,我注意到前者正在被设置,但是所有与它们相关联的键仍然是Constraints
。我把它们设定为真的:
for fk in table.foreign_keys:
fk.use_alter=True
fk.constraint.use_alter=True
这似乎产生了我正在寻找的SQL,并且正确地创建了没有
False
的表,而且CircularDependencyErrors
似乎工作正常,没有错误。实际上,我能够重构我的代码并以正确的方式做事情!对于任何希望使用SQLAlchemy使用复杂FKs进行DB-->DB反射的人,此答案和Tyler Lesmann's article适合您。
*更新:*使用此方法已通过同行评审,现正用作生产代码。看来效果不错!