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


16

在使用生产数据的副本测试某些迁移脚本(脚本与开发数据运行良好)时,我发现了一个奇怪的情况。约束已更改,因此我正在发出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;

DROP命令工作正常,但添加命令失败。现在,我陷入了一个恶性循环。我不能删除该约束,因为它不存在(初始删除按预期方式工作):

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

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

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

我输入A_DUP_CALLE_UK1到SQL Developer的“ 搜索”框中,然后就可以了!所有者,表名,表景...一切都匹配:它不是具有相同名称的其他对象,这我的原始约束。该表出现在约束详细信息中,但约束没有出现在表的详细信息中。

我的问题:

  • 这有什么解释?
  • 在实时服务器中进行真正的升级时,如何确保不会发生这种情况?

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


也许它是作为其他类型的对象创建的,而不是唯一的约束?也许唯一索引..
玛丽安(Marian)

可以使用表名前后的引号运行初始创建吗?这将使名称区分大小写。如果是这样,您可以使用引号和相同的大小写删除。
亚当·巴特勒

Answers:


13

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

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  

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


这就是问题所在。该exp命令生成的转储文件包含CREATE UNIQUE INDEX "A_DUP_CALLE_UK1" ...原始脚本集中不存在的语句。
阿尔瓦罗·冈萨雷斯

6

似乎很奇怪。

您可以运行:

 SELECT *
 FROM user_objects
 WHERE object_name = 'A_DUP_CALLE_UK1'

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

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

如果表中包含有价值的数据,则可以在以下日期对其进行备份:

CREATE TABLE old_data
AS
SELECT *
FROM A_DUP_CALLE;

重新创建表格后,就可以

INSERT INTO A_DUP_CALLE (col1, col2, col3) 
SELECT col1, col2, col3
FROM old_data

恢复数据。


4

几分钟前我也遇到了同样的问题...并且找到了解释。

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

通过删除约束,索引将使用相同的索引名称保留在那里,因此,如果您仅执行

alter table t drop constraint u1;

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

drop index u1;

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

alter table t drop constraint u1 including indexes;

哪个分贝?包括在Oracle中不起作用
Derick

1

主键约束随索引一起提供。您删除约束但不删除索引。校验:

select * from ALL_OBJECTS where OBJECT_NAME = 'PK_TBL_CONSTR';

你看到的OBJECT_TYPEINDEX

两者都一样:

alter table TBL drop constraint PK_TBL_CONSTR;
drop index PK_TBL_CONSTR;

1

做这个

ALTER TABLE A_DUP_CALLE
DROP CONSTRAINT "A_DUP_CALLE_UK1";

会的。

图片: 在此处输入图片说明


不,它不起作用。您的陈述与问题中的第一条陈述完全相同ALTER TABLE A_DUP_CALLE DROP CONSTRAINT A_DUP_CALLE_UK1;
a_horse_with_no_name 2014年

它确实有效。从今天中午开始,我遇到了同样的问题,因此寻找解决方案。有时,CONSTRAINTS可能是以区分大小写的方式创建的,在这种情况下,您需要在删除约束名称时将其放在双引号中
萨钦(Sachin)2014年

它为我工作。我没有明确命名约束,因此系统给了它自己的生成名称Relationship142,其他NOT NULL约束被赋予了name SYS_C0015910。因此,SYS_C0015910已成功用简单的ALTER查询删除,但Relationship142需要双引号
萨钦

1
您使用双引号创建了约束,例如:的alter table ... add constraint "Relationship143" ... "Relationship143"名称与确实不同RELATIONSHIP143。但是"RELATIONSHIP143"RELATIONSHIP143相同的
a_horse_with_no_name 2014年

2
Oracle(数据库)永远不会"Relationship143"自己创建一个名称。可能是您执行此操作的工具之一。无论如何:就目前情况而言,在原始问题的背景下,您的答案完全是错误的。
a_horse_with_no_name 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.