2

我在脚本中使用 SA,我将使用该脚本定期将 mysql 表的子集从“生产”副本“复制”到开发/测试系统。我编写了代码来简单地反映源表和meta.create_all(destination_engine). 由于 FK 的性质,我现在知道我需要use_alter=True在创建表时应用到表上的 ForeignKey,这样我就不会遇到 CircularDependencyErrors 或其他问题。我需要假设在我浏览元数据之前我不知道有多少个 FK 或他们的名字。

我是 SA 新手,通常是 Java 程序员(如您所说:D)。我试图改变 use_alter attr。首先迭代:

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 属性后不会抛出 CircularDependencyError 。如果我删除该代码, create_all() 不起作用。它似乎并没有从创建中删除 FK...

这显然是行不通的。然后我阅读了 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)

我猜想单独反映每个表use_alter=True,然后添加 FK 定义会起作用,但我不能假设 FK/列的名称和值或#。我读了很多关于使用DeclarativeBase来做这样的事情,但我不确定它是如何工作的......

如何获取我的任意表列表,反映它们,然后在它们各自的外键上覆盖 use_alter 选项?我在想这个错误的方式吗?

4

1 回答 1

5

答案最终出现在问题内部(想象一下……)。虽然每个ForeignKey对象都有一个use_alter可以设置的值,但也有一个可以设置的单独属性(我在API 文档Constraints中找不到这个。通过 PyDev 的调试器运行它后,我注意到前者正在设置,但所有与它们关联的键仍然. 我因此将它们设置为 true:ConstraintsFalse

for fk in table.foreign_keys:
    fk.use_alter=True
    fk.constraint.use_alter=True

这似乎产生了我正在寻找的 SQL,并且表被正确创建,没有错误CircularDependencyErrorsmetadata.sorted_tables似乎工作正常,没有错误。我实际上能够重构我的代码并以正确的方式做事!

对于希望使用 SQLAlchemy 使用复杂 FK 进行 DB-->DB 反射的任何人,此答案和Tyler Lesmann 的文章都适合您。

*更新:*使用此方法已通过同行评审,现在被用作生产代码。似乎运作良好!

于 2012-09-06T21:01:58.233 回答