2015-02-25 5 views
0

Мне нужно создать таблицу на основе существующей таблицы в той же (Oracle) схеме. Я не хочу иметь никаких ограничений для новой таблицы, даже если исходная таблица может иметь один или несколько.Sqlalchemy - core - создающая копия существующей таблицы

Я попытался создать новую таблицу из исходной таблицы, используя 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» (это НЕ НУЛЬНЫЕ контрольные ограничения).

Исключение:

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' 

Есть ли другой лучший подход к этому?

ответ

2

Похоже, я решил свой собственный вопрос.

Исходная таблица имела три ограничения "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.

Я знаю, что мне не нужно было все это делать, чтобы создать новую таблицу с оригинальным определением таблицы, но пока это работает.

+0

Обязательно. Но мне придется подождать 2 дня, прежде чем я смогу это принять. – Gaurav

Смежные вопросы