SQLalchemy - 核心 - 创建现有副本 table
Sqlalchemy - core - creating copy of an existing table
我需要基于同一 (Oracle) 架构中的现有 table 创建一个 table。我不想对新的 table 有任何限制,即使原来的 table 可能有一个或多个
我尝试使用 column.copy()
从原始 table 创建新的 table,但由于某种原因,我无法在创建新的 table 在数据库中。
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 似乎不知道在数据库中 new table 上创建的约束的名称。我可以看到新的 table 带有约束名称,例如 "SYS_C00450822" 和 "SYS_C00450823"(这些不是 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'
还有其他更好的方法吗?
看来我已经解决了自己的问题。
原来的 table 有三个 "NOT NULL" 约束(没有明确命名,所以它们被命名为“SYS_C00450822
”等)和一个 PK 约束(命名为,比方说,"TABLE_PK").
当我仅使用原始 table 中的列创建副本时, 而不是约束 ,新的 table 是使用 4 个约束创建的,全部具有系统生成的名称如 "SYS_C00450822".
在删除约束时,sqlalchemy 没有得到任何 "name" 的约束,正如问题中提到的那样,并且在行的某处,导致行 lc_value = value.lower()
出现问题,因为值(我认为是 NoneType 的 "name",为空)。
所以我更改了代码以从原始 table 中创建也具有约束的新 table - 但重命名约束的名称,以便它不会与现有的原始 table约束)。
这以相同的方式创建了三个 "NOT NULL" CHECK 约束,但 PK 约束现在 定义为名称 ,例如 "TABLE_PK_2"。
然后通过 DropConstraint
调用安全地完成了。
我知道我不应该为了创建一个具有原始 table 定义的新 table 而做所有这些,但就目前而言,这似乎可行。
我需要基于同一 (Oracle) 架构中的现有 table 创建一个 table。我不想对新的 table 有任何限制,即使原来的 table 可能有一个或多个
我尝试使用 column.copy()
从原始 table 创建新的 table,但由于某种原因,我无法在创建新的 table 在数据库中。
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 似乎不知道在数据库中 new table 上创建的约束的名称。我可以看到新的 table 带有约束名称,例如 "SYS_C00450822" 和 "SYS_C00450823"(这些不是 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'
还有其他更好的方法吗?
看来我已经解决了自己的问题。
原来的 table 有三个 "NOT NULL" 约束(没有明确命名,所以它们被命名为“SYS_C00450822
”等)和一个 PK 约束(命名为,比方说,"TABLE_PK").
当我仅使用原始 table 中的列创建副本时, 而不是约束 ,新的 table 是使用 4 个约束创建的,全部具有系统生成的名称如 "SYS_C00450822".
在删除约束时,sqlalchemy 没有得到任何 "name" 的约束,正如问题中提到的那样,并且在行的某处,导致行 lc_value = value.lower()
出现问题,因为值(我认为是 NoneType 的 "name",为空)。
所以我更改了代码以从原始 table 中创建也具有约束的新 table - 但重命名约束的名称,以便它不会与现有的原始 table约束)。
这以相同的方式创建了三个 "NOT NULL" CHECK 约束,但 PK 约束现在 定义为名称 ,例如 "TABLE_PK_2"。
然后通过 DropConstraint
调用安全地完成了。
我知道我不应该为了创建一个具有原始 table 定义的新 table 而做所有这些,但就目前而言,这似乎可行。