【问题标题】:How do I copy Unique constraint in Oracle with SQLAlchemy?如何使用 SQLAlchemy 在 Oracle 中复制唯一约束?
【发布时间】:2015-11-06 13:06:38
【问题描述】:

我有一个必须复制的表(我无法控制它)。目标架构可以与原始架构相同,因此所有索引和约束都必须在没有名称的情况下隐式定义。

我将 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 的方法吗?在这种情况下,您将拥有约束的名称,它们将不同于现有的约束。
  • 对不起,我的意思是设置索引名称
  • 谢谢@pavel_form,我没想到。这仍然是一种解决方法,但如果我找不到更好的方法,我会继续这样做。

标签: python oracle python-3.x sqlalchemy


【解决方案1】:

“UNIQUE INDEX”表示使用Index 构造。它的 DDL 不会在 CREATE TABLE 中发出。听起来您正在寻找 UniqueConstraint 构造。在这种情况下,Oracle 很可能会返回有关您第一次创建为 UniqueConstraint 对象的反映信息作为具有 unique=True 的 Index 对象(这些构造是“不同的”,但在许多后端它们是同义词和/或混合搭配,有时甚至是镜像,这完全令人困惑)。

在一天结束时,如果您希望将 UNIQUE 关键字作为内联约束,您需要使用 UniqueConstraint 对象,并且您需要从表中删除此 Index - 您可能会得到离开table.indexes.remove(index)Index 对象不会在 table.constraints 中。您可能希望以更编程的方式而不是使用 tometadata() 来“复制”表。不妨考虑直接使用inspection interface,然后从中构建您想要的Table

【讨论】:

    猜你喜欢
    • 2018-08-23
    • 1970-01-01
    • 1970-01-01
    • 2018-09-11
    • 2016-08-22
    • 2017-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多