【问题标题】:Oracle unique constraint remove and modifyoracle唯一约束删除和修改
【发布时间】:2015-11-02 12:54:05
【问题描述】:

我有一个表和两个约束——其中一个约束是微不足道的,我想从现有的这个表中删除它——它有数据。

所以下面是表格--

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');

下面是我正在遵循的步骤

  1. 禁用 T1_U 约束--

    ALTER TABLE T1 DISABLE CONSTRAINT T1_U;

  2. 重命名索引 --

    ALTER INDEX T1_U1 RENAME TO T1_U;

  3. 删除 T1_U。

    ALTER TABLE T1 DROP CONSTRAINT T1_U;

现在,如果我检查USER_OBJECTS,我仍然可以看到T1_U。 -- 为什么会这样?

所以我尝试使用DROP INDEX T1_U;——这是不正确的。

  1. 然后我尝试修改T1_U-- 按预期失败。

问题:能否请您告诉我有什么办法可以实现上述目标?

谢谢。

【问题讨论】:

    标签: oracle11g constraints unique-constraint


    【解决方案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: 无法删除用于强制执行唯一/主键的索引

    希望这可以为您解决第一个问题。

    对于您的第二个问题 - “您能告诉我我们有什么办法可以实现上述目标吗?”这完全取决于您要做什么。希望我上面的解释能够让您弄清楚您的示例中发生了什么以及为什么,并让您能够回答自己的问题。

    如果还没有,请更新您的问题,提供有关您要达到的目标的更多信息。

    【讨论】: