我有一个表和2个约束 - 其中一个约束是微不足道的,我想从现有的表中删除它 - 它有数据。
以下是表格 -
create table t1 (aa varchar2(10),bb varchar2(10),cc varchar2(10),dd varchar2(10),ee varchar2(10));
insert into T1 values ('a','b','c','x','y');
insert into T1 values ('d','e','f','u','w');
insert into T1 values ('g','h','i','q','r');
insert into t1 values ('j','k','l','v','z');
alter table T1 add constraint T1_U unique (AA,BB);
alter table T1 add constraint T1_U1 unique (cc,dd);
现在,我们有2个约束,其中,我想删除T1_U1并修改 T1_U。
通过 -
可以看到2个约束SELECT * FROM USER_OBJECTS WHERE OBJECT_NAME IN ('T1_U','T1_U1');
以下是我要遵循的步骤
禁用T1_U约束 -
ALTER TABLE T1 DISABLE CONSTRAINT T1_U;
重命名索引 -
ALTER INDEX T1_U1 RENAME TO T1_U;
删除T1_U。
ALTER TABLE T1 DROP CONSTRAINT T1_U;
现在,如果我检查USER_OBJECTS
,我仍然可以看到T1_U
。 - 为什么会这样?
所以我尝试使用DROP INDEX T1_U;
- 这是不正确的。
T1_U
- 按预期失败了。问题:请告诉我有什么方法可以实现上述目标吗?
感谢。
答案 0 :(得分:1)
如果您还查看user_constraints:
,这很容易解释create table t1 (aa varchar2(10),bb varchar2(10),cc varchar2(10),dd varchar2(10),ee varchar2(10));
insert into T1 values ('a','b','c','x','y');
insert into T1 values ('d','e','f','u','w');
insert into T1 values ('g','h','i','q','r');
insert into t1 values ('j','k','l','v','z');
alter table T1 add constraint T1_U unique (AA,BB);
alter table T1 add constraint T1_U1 unique (cc,dd);
SELECT object_name, object_type FROM USER_OBJECTS WHERE OBJECT_NAME IN ('T1_U','T1_U1');
OBJECT_NAME OBJECT_TYPE
------------ -------------------
T1_U INDEX
T1_U1 INDEX
select constraint_name, constraint_type, table_name, status, index_name from user_constraints where constraint_name IN ('T1_U','T1_U1');
CONSTRAINT_NAME CONSTRAINT_TYPE TABLE_NAME STATUS INDEX_NAME
---------------- --------------- ----------- -------- -----------
T1_U U T1 ENABLED T1_U
T1_U1 U T1 ENABLED T1_U1
存在约束及其相应的索引。
ALTER TABLE T1 DISABLE CONSTRAINT T1_U;
SELECT object_name, object_type FROM USER_OBJECTS WHERE OBJECT_NAME IN ('T1_U','T1_U1');
OBJECT_NAME OBJECT_TYPE
------------ -------------------
T1_U1 INDEX
select constraint_name, constraint_type, table_name, status, index_name from user_constraints where constraint_name IN ('T1_U','T1_U1');
CONSTRAINT_NAME CONSTRAINT_TYPE TABLE_NAME STATUS INDEX_NAME
---------------- --------------- ----------- -------- -----------
T1_U1 U T1 ENABLED T1_U1
T1_U U T1 DISABLED
现在约束T1_U被禁用,现在不再需要强制执行索引的索引T1_U,并且 - 因为Oracle知道约束是由约束创建的而不是单独创建的(我不确定如何,但确实如此) - 它知道不再需要索引,因此可以删除它。 (您可以通过在创建约束之前先创建索引来确认这一点,并且当禁用约束时,索引仍然存在。)
ALTER INDEX T1_U1 RENAME TO T1_U;
SELECT object_name, object_type FROM USER_OBJECTS WHERE OBJECT_NAME IN ('T1_U','T1_U1');
OBJECT_NAME OBJECT_TYPE
------------ -------------------
T1_U INDEX
select constraint_name, constraint_type, table_name, status, index_name from user_constraints where constraint_name IN ('T1_U','T1_U1');
CONSTRAINT_NAME CONSTRAINT_TYPE TABLE_NAME STATUS INDEX_NAME
---------------- --------------- ----------- -------- -----------
T1_U1 U T1 ENABLED T1_U
T1_U U T1 DISABLED
因为不再有索引T1_U,我们可以将T1_U1索引重命名为T1_U。但请注意,这并不会改变与之关联的约束 - 它仍然属于T1_U1约束。
ALTER TABLE T1 DROP CONSTRAINT T1_U;
SELECT object_name, object_type FROM USER_OBJECTS WHERE OBJECT_NAME IN ('T1_U','T1_U1');
OBJECT_NAME OBJECT_TYPE
------------ -------------------
T1_U INDEX
select constraint_name, constraint_type, table_name, status, index_name from user_constraints where constraint_name IN ('T1_U','T1_U1');
CONSTRAINT_NAME CONSTRAINT_TYPE TABLE_NAME STATUS INDEX_NAME
---------------- --------------- ----------- -------- -----------
T1_U1 U T1 ENABLED T1_U
因此,当您删除不再具有关联索引的T1_U约束时,除了T1_U约束之外不会删除任何其他约束。重命名的T1_U索引属于T1_U1约束,因此,您不会期望它被删除。
此外,如果你现在试着这样做:
drop index t1_u;
你得到:
ORA-02429:无法删除用于强制执行唯一/主键的索引
希望这能为您解决第一个问题。
关于你的第二个问题 - "你可以告诉我有什么办法可以实现上述目标吗?"这完全取决于你想要做什么。希望我上面的解释能让你弄清楚你的例子中发生了什么,为什么,并让你回答你自己的问题。
如果还没有,请更新您的问题,并提供有关您尝试实现的内容的更多信息。