不能删除不存在的约束,也不能创建它

Álv*_*lez 19 oracle oracle-10g oracle-xe

在使用生产数据的副本测试一些迁移脚本(脚本与开发数据一起运行良好)时,我发现了一个奇怪的情况。CONSTRAINT 已更改,因此我发出 DROP + ADD 命令:

ALTER TABLE A_DUP_CALLE
DROP CONSTRAINT A_DUP_CALLE_UK1;

ALTER TABLE A_DUP_CALLE
ADD CONSTRAINT A_DUP_CALLE_UK1 UNIQUE (
    CONTROL_ID,
    CALLE_AYTO_DUPL
)
ENABLE;
Run Code Online (Sandbox Code Playgroud)

DROP 命令运行良好,但 ADD 命令失败。现在,我陷入了一个恶性循环。我无法删除约束,因为它不存在(初始删除按预期工作):

ORA-02443: 无法删除约束 - 不存在的约束

我无法创建它,因为名称已经存在:

ORA-00955: 名称已被现有对象使用

A_DUP_CALLE_UK1在 SQL Developer 的搜索框中输入内容,然后……就在那里!所有者、表名、表景观……一切都匹配:它不是同名的不同对象,它我的原始约束。该表出现在约束详细信息中,但该约束未出现在表的详细信息中。

我的问题:

  • 对此有何解释?
  • 当我在实时服务器中进行真正的升级时,如何确保它不会发生?

(服务器是 10g XE,我没有足够的声望来创建标签。)

Jac*_*las 14

猜测我会说玛丽安是对的,这是由具有相同名称的唯一索引和约束引起的,例如:

create table t( k1 integer, k2 integer, 
                constraint u1 unique(k1,k2) using index(create unique index u1 on t(k1,k2)),
                constraint u2 unique(k2,k1) using index u1);

select count(*) from user_indexes where index_name='U1';

COUNT(*)               
---------------------- 
1  

alter table t drop constraint u1;

select count(*) from user_indexes where index_name='U1';

COUNT(*)               
---------------------- 
1  
Run Code Online (Sandbox Code Playgroud)

通常,当您添加唯一约束时,会创建一个具有相同名称的唯一索引 - 但索引和约束不是一回事。看看all_indexes,看看是否有一个叫做索引A_DUP_CALLE_UK1,并尝试找出如果你删除它之前,它由别的东西!


a_h*_*ame 6

看起来很奇怪。

你可以运行:

 SELECT *
 FROM user_objects
 WHERE object_name = 'A_DUP_CALLE_UK1'
Run Code Online (Sandbox Code Playgroud)

检查 Oracle 抱怨的对象类型。然后,您可以为此运行适当的 DROP 语句。

我能想到的唯一的另一件事是完全删除表格DROP TABLE A_DUP_CALLE CASCADE CONSTRAINTS以摆脱属于该表格的所有内容,然后完全重新创建它。

如果该表包含有价值的数据,您可以在此之前对其进行备份:

CREATE TABLE old_data
AS
SELECT *
FROM A_DUP_CALLE;
Run Code Online (Sandbox Code Playgroud)

重新创建表后,您可以执行

INSERT INTO A_DUP_CALLE (col1, col2, col3) 
SELECT col1, col2, col3
FROM old_data
Run Code Online (Sandbox Code Playgroud)

来恢复数据。


小智 6

几分钟前我遇到了同样的问题……我找到了一个解释。

通过创建主键,Oracle 创建了两个对象:一个约束和一个控制“UNIQUE”部分的索引。

通过删除约束,索引保留在那里,使用索引的相同名称,所以如果你只执行

alter table t drop constraint u1;
Run Code Online (Sandbox Code Playgroud)

您将只删除约束。要删除索引,您需要执行

drop index u1;
Run Code Online (Sandbox Code Playgroud)

这应该可以完成工作。或者,您可以使用以下命令同时执行这两个命令

alter table t drop constraint u1 including indexes;
Run Code Online (Sandbox Code Playgroud)