Нахождение призрачного ограничения из базы данных Oracle - PullRequest
15 голосов
/ 03 марта 2010

У меня было ограничение в таблице


CREATE TABLE "USERSAPPLICATIONS" (
    "USERID" NUMBER NOT NULL ,
    "APPLICATIONNAME" VARCHAR2 (30) NOT NULL ,
 CONSTRAINT "PK_USERSAPPLICATIONS" PRIMARY KEY ("USERID","APPLICATIONNAME") 
) 
/

Две недели назад я изменил таблицу, добавил несколько столбцов, удалил ограничение "PK_USERSAPPLICATIONS" и добавил суррогатный ключ. Я вижу в Oracle SQL Developer, что ограничение PK_USERSAPPLICATIONS больше не существует.

Независимо от этого, когда я пытаюсь добавить две записи с одинаковой комбинацией userid / applicationName, я получаю сообщение об ошибке


SQL Error: ORA-00001: unique constraint (ACCOUNTMP1.PK_USERSAPPLICATIONS) violated
00001. 00000 -  "unique constraint (%s.%s) violated"
*Cause:    An UPDATE or INSERT statement attempted to insert a duplicate key.
           For Trusted Oracle configured in DBMS MAC mode, you may see
           this message if a duplicate entry exists at a different level.
*Action:   Either remove the unique restriction or do not insert the key.

Когда я выполняю заявление


SELECT *
FROM   user_cons_columns
WHERE  constraint_name = 'PK_USERSAPPLICATIONS' 

Я получаю ноль строк. Как это может быть? Oracle не должен знать об ограничении PK_USERSAPPLICATIONS, так как он был удален уже несколько недель назад, и я не вижу его в базе данных.

Ответы [ 2 ]

31 голосов
/ 03 марта 2010

У вас все еще есть индекс, который использовался этим ограничением? Потому что, если вы не включили предложение DROP INDEX при снятии ограничения, оно все равно останется. Начните с

SELECT * 
FROM   user_indexes
WHERE  index_name = 'PK_USERSAPPLICATIONS'  
/

В качестве альтернативы

select index_name 
from user_indexes
where table_name = 'USERSAPPLICATIONS'
and  uniqueness='UNIQUE' 
/

или

select index_name 
from user_ind_columns
where table_name = 'USERSAPPLICATIONS'
and  column_name in ('USERID' ,'APPLICATIONNAME')  
/

1012 * редактировать *

Подтверждение концепции

SQL> create table t23 (id number not null, alt_key varchar2(10) not null)
  2  /

Table created.

SQL> create unique index t23_idx on t23 (id)
  2  /

Index created.

SQL> alter table t23 add constraint t23_pk primary key (id) using index
  2  /

Table altered.

SQL> insert into t23 values (1, 'SAM I AM')
  2  /

1 row created.

SQL> insert into t23 values (1, 'MR KNOX')
  2  /
insert into t23 values (1, 'MR KNOX')
*
ERROR at line 1:
ORA-00001: unique constraint (APC.T23_PK) violated

SQL>

Так что ограничение работает. Что произойдет, если мы отбросим его без предложения DROP INDEX?

SQL> alter table t23 drop constraint t23_pk
  2  /

Table altered.

SQL> insert into t23 values (1, 'MR KNOX')
  2  /
insert into t23 values (1, 'MR KNOX')
*
ERROR at line 1:
ORA-00001: unique constraint (APC.T23_IDX) violated


SQL>

Обратите внимание на незначительные изменения в сообщении об ошибке. Второй сбой ссылается на имя индекса, тогда как в исходном сообщении указывается ограничение. Если имя индекса совпадает с именем ограничения, это будет трудно диагностировать.

Если вы предварительно не создадите уникальный индекс явно, Oracle по умолчанию будет создавать неуникальный индекс. Следовательно, удаление ограничения без удаления индекса не вызывает этой проблемы. (Предостерегаем, что это поведение верно для 11g. Я предполагаю - но не могу быть уверен - что это также относится к более ранним версиям).

1 голос
/ 03 марта 2010

Попробуйте проверить индекс для этих столбцов. В некоторых случаях индекс, связанный с ограничением, не удаляется после удаления ограничения

...