У меня есть таблица (над которой у меня нет контроля), которую я должен скопировать. Целевая схема может быть такой же, как исходная, поэтому все индексы и ограничения должны быть определены без имени, неявно.
Я использую Python 3.4.3 с SQLAlchemy 1.0.8 и cx_oracle 5.2.
Таблица такая:
CREATE TABLE "MY_TABLE"
( "ITEMID" NUMBER(*,0) NOT NULL ENABLE,
"LABEL" NVARCHAR2(80) NOT NULL ENABLE,
"FIRSTCHILDID" NUMBER(*,0) NOT NULL ENABLE,
"LASTCHILDID" NUMBER(*,0) NOT NULL ENABLE,
"DEFAULTPARENTID" NUMBER(*,0) NOT NULL ENABLE,
"PICTUREID" NUMBER(6,0) NOT NULL ENABLE,
"SECURITYID" NUMBER(*,0) NOT NULL ENABLE,
PRIMARY KEY ("ITEMID")
UNIQUE ("LABEL"));
Код, который я использую, находится по адресу https://gist.github.com/toyg/9fb541ff3dbc8c175329. но суть его в следующем (smeta и dmeta являются исходными и целевыми метаданными, связанными):
table = Table(table_name, smeta, autoload=True)
target_name = prefix + str(table.name)
target_table = table.tometadata(dmeta, name=target_name)
for constraint in target_table.constraints:
constraint.name = None
target_table.metadata.create_all(dengine)
Это терпит неудачу с этой ошибкой:
sqlalchemy.exc.DatabaseError: (cx_Oracle.DatabaseError)
ORA-00955: name is already used by an existing object
[SQL: b'CREATE UNIQUE INDEX sys_c009016 ON "TMP_MY_TABLE" (label)']
Это связано с тем, что SQLAlchemy пытается создать уникальный индекс после создания таблицы, когда уже слишком поздно: CREATE INDEX требует имя, поэтому SA использует то же имя, что и существующее, и это не удается.
Я попытался установить имя индекса в None перед созданием, чтобы дать SA подсказку, но это приводит к ошибкам, потому что он всегда ожидает там строку.
Есть ли способ сказать SA, чтобы он просто сразу же добавил чертову фразу UNIQUE в таблицу DDL?
constraint.name = prefix + constraint.name
? В этом случае у вас будут имена для ограничений, и они будут отличаться от существующих ограничений. - person pavel_form   schedule 13.08.2015