mysql - SQLAlchemy 动态覆盖反射列

标签 mysql reflection sqlalchemy python-2.7

我在脚本中使用 SA,我将使用该脚本定期将 mysql 表的子集从“生产”副本“复制”到开发/测试系统。我编写了代码来简单地反射(reflect)源表和 meta.create_all(destination_engine)。由于 FK 的性质,我现在知道在创建表上的外键时需要将 use_alter=True 应用到它们,这样就不会出现 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)

编辑:需要注意的是,在我像上面那样设置 use_alter 属性后,create_all() 不会抛出 CircularDependencyError 。如果我删除该代码,create_all() 将不起作用。它似乎并没有从创建中删除 FK...

这显然行不通。然后我读了Overriding Reflected Columns在 SA 文档中,示例为:

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)

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

如何获取任意表列表,反射(reflect)它们,然后覆盖它们各自外键上的 use_alter 选项?我是否以错误的方式思考这个问题?

最佳答案

答案最终就在问题内部(想象一下......)。虽然每个ForeignKey对象有一个 use_alter可以设置的值,Constraints还有一个可以设置的单独属性(我无法在 API Documentation 中找到它。通过 PyDev 的调试器运行它后,我注意到前者已被设置,但所有与 Constraints 关联的键仍然是 False 。我这样将它们设置为 true:

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

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

对于任何想要使用 SQLAlchemy 进行 DB-->DB 反射(reflect)复杂 FK 的人来说,这个答案和 Tyler Lesmann's article适合你。

*更新:* 使用此方法已通过同行评审,现已用作生产代码。看起来效果很好!

关于mysql - SQLAlchemy 动态覆盖反射列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12303439/

相关文章:

python - 创建后出现未知数据库错误(sqlalchemy)

mysql - SQL查询一直提示: 00904. 00000 - "%s: invalid identifier"

c# - 如何通过主键获取大量数据库表记录?

java - 创建通用方法以适应接口(interface)和通用父类

c# - 为什么这个克隆不起作用?

java - 在 maven 插件中扫描 java 类路径

python - 带有默认数据类的 SQLAlchemy 不填充 postgres 数据库

mysql - Laravel 路由参数未修剪(通常在添加空格时有效)

mysql - 按非标准天数结束计算天数

sqlalchemy - 防止写入特定表(只读表)