【问题标题】:Sqlalchemy - core - creating copy of an existing tableSqlalchemy - 核心 - 创建现有表的副本
【发布时间】:2015-04-28 04:06:17
【问题描述】:

我需要基于相同 (Oracle) 架构中的现有表创建表。我不想对新表有任何约束,即使原始表可能有一个或多个。

我尝试使用column.copy()从原始表创建新表,但由于某种原因,在数据库中创建新表后我无法删除约束。

def clone_table_approach_1(original_table, connection, metadata):
    try:
        new_table_name = original_table.name + '_sync'
        columns = [c.copy() for c in original_table.columns]
        new_table = Table(new_table_name, metadata, quote=False, *columns)

        # Create table in database
        if not new_table.exists():
            new_table.create()
        else:
            raise Exception("New table already exists")

        # Remove constraints from new table if any
        for constraint in new_table.constraints:
            connection.execute(DropConstraint(constraint))

        # Return table handle for newly created table
        final_cloned_table = Table(new_table, metadata, quote=False)
        return final_cloned_table

    except:
        # Drop if we did create a new table
        if new_table.exists():
            new_table.drop()
        raise

删除约束时失败。似乎 sqlalchemy 不知道在数据库中的新表上创建的约束的名称。我可以看到带有约束名称的新表,例如“SYS_C00450822”和“SYS_C00450823”(这些是 NOT NULL 检查约束)。

例外:

Traceback (most recent call last):
  File "/home/gaurav/myprojects/python/sync/test_table_copy.py", line 163, in <module>
    t_product_new = clone_table_approach_1(t_product, target_conn, target_metadata)
  File "/home/gaurav/myprojects/python/sync/test_table_copy.py", line 57, in clone_table_approach_1
    connection.execute(DropConstraint(constraint))
  File "/home/gaurav/.local/lib/python3.4/site-packages/sqlalchemy/engine/base.py", line 729, in execute
    return meth(self, multiparams, params)
  File "/home/gaurav/.local/lib/python3.4/site-packages/sqlalchemy/sql/ddl.py", line 69, in _execute_on_connection
    return connection._execute_ddl(self, multiparams, params)
  File "/home/gaurav/.local/lib/python3.4/site-packages/sqlalchemy/engine/base.py", line 777, in _execute_ddl
    compiled = ddl.compile(dialect=dialect)
  File "<string>", line 1, in <lambda>
  File "/home/gaurav/.local/lib/python3.4/site-packages/sqlalchemy/sql/elements.py", line 493, in compile
    return self._compiler(dialect, bind=bind, **kw)
  File "/home/gaurav/.local/lib/python3.4/site-packages/sqlalchemy/sql/ddl.py", line 27, in _compiler
    return dialect.ddl_compiler(dialect, self, **kw)
  File "/home/gaurav/.local/lib/python3.4/site-packages/sqlalchemy/sql/compiler.py", line 199, in __init__
    self.string = self.process(self.statement, **compile_kwargs)
  File "/home/gaurav/.local/lib/python3.4/site-packages/sqlalchemy/sql/compiler.py", line 222, in process
    return obj._compiler_dispatch(self, **kwargs)
  File "/home/gaurav/.local/lib/python3.4/site-packages/sqlalchemy/sql/visitors.py", line 80, in _compiler_dispatch
    return meth(self, **kw)
  File "/home/gaurav/.local/lib/python3.4/site-packages/sqlalchemy/sql/compiler.py", line 2518, in visit_drop_constraint
    self.preparer.format_constraint(drop.element),
  File "<string>", line 1, in <lambda>
  File "/home/gaurav/.local/lib/python3.4/site-packages/sqlalchemy/sql/compiler.py", line 2928, in format_constraint
    return self.quote(constraint.name)
  File "/home/gaurav/.local/lib/python3.4/site-packages/sqlalchemy/sql/compiler.py", line 2893, in quote
    if self._requires_quotes(ident):
  File "/home/gaurav/.local/lib/python3.4/site-packages/sqlalchemy/sql/compiler.py", line 2864, in _requires_quotes
    lc_value = value.lower()
AttributeError: 'NoneType' object has no attribute 'lower'

还有其他更好的方法吗?

【问题讨论】:

    标签: python oracle sqlalchemy


    【解决方案1】:

    看来我已经解决了自己的问题。

    原始表具有三个“NOT NULL”约束(未明确命名,因此它们被命名为“SYS_C00450822”等)和一个 PK 约束(例如命名为“TABLE_PK”)。

    当我只使用原始表中的列创建副本时,但没有约束,新表创建时有 4 个约束,所有约束都具有系统生成的名称,例如“SYS_C00450822”。

    在删除约束时,sqlalchemy 没有得到任何约束的“名称”,正如问题中提到的那样,并且在某个地方,这导致了lc_value = value.lower() 行中的问题,因为值(我认为是"name",为 null,属于 NoneType)。

    所以我更改了代码以从原始表创建带有约束的新表 - 但重命名约束的名称,使其不会与现有的原始表约束冲突)。

    这以相同的方式创建了三个“NOT NULL”CHECK 约束,但 PK 约束现在使用名称定义,例如“TABLE_PK_2”。

    然后通过DropConstraint 呼叫安全地完成此操作。

    我知道我不应该仅仅为了创建一个具有原始表定义的新表而做所有这些,但目前看来,这似乎可行。

    【讨论】:

    • 当然。但我得等2天才能接受。
    猜你喜欢
    • 2019-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多