我在一个脚本中使用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适合您。
*更新:*使用此方法已通过同行评审,现正用作生产代码。看来效果不错!

07-25 23:33