Неможливо скинути неіснуюче обмеження і його також не можна створити


16

Під час тестування деяких сценаріїв міграції з копією виробничих даних (сценарії справні із даними про розробку) я виявив цікаву ситуацію. 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;

Команда DROP спрацювала нормально, але додавання не вдалося. Тепер я перебуваю в порочному колі. Я не можу скинути обмеження, оскільки воно не існує (початкове падіння працювало як очікувалося):

ORA-02443: Неможливо скинути обмеження - неіснуюче обмеження

І я не можу створити його, оскільки ім'я вже існує:

ORA-00955: ім'я вже використовується існуючим об'єктом

Я A_DUP_CALLE_UK1набираю поле пошуку для розробника SQL і ... ось воно! Власник, ім'я таблиці, Tablescape ... все збігається: це не інший об'єкт з тим же ім'ям, що це моє первинне обмеження. Таблиця відображається в деталях обмеження, але обмеження не відображається в деталях таблиці.

Мої запитання:

  • Яке пояснення цьому?
  • Як я можу впевнитись, що цього не відбудеться, коли я здійснять реальне оновлення на живому сервері?

(Сервер 10g XE, мені не вистачає репутації для створення тегу.)


Можливо, він був створений як інший тип об'єкта і не є унікальним обмеженням? Можливо, унікальний індекс ..
Marian

Чи можна було виконати початкове створення цитатами навколо назви таблиці? Це зробить назву регістру імен. Якщо так, ви можете кинути цитати і той самий випадок.
Адам Батлер

Відповіді:


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;

який db? в тому числі не працює в оракулі
Derick

1

Первинне обмеження ключа має індекс. Ви скидаєте обмеження, але не індексуєте. Перевірка:

select * from ALL_OBJECTS where OBJECT_NAME = 'PK_TBL_CONSTR';

і бачите, OBJECT_TYPEє INDEX.

Так само робити:

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

Він працював фактично. У мене були такі ж проблеми з сьогоднішнього полудня, і в пошуку рішення я натрапив на це. Іноді CONSTRAINTS, можливо, були створені залежно від регістру, і в цьому випадку вам потрібно буде ввести ім'я обмеження у подвійні лапки, коли ви його відкинете.
Сачин

І це працювало на мене. Я не назвав обмеження прямо, тому система дала йому власне генероване ім'я, Relationship142а іншим NOT NULLобмеженням було надано ім'я SYS_C0015910. Так SYS_C0015910було успішно видалено простим запитом ALTER, але Relationship142потрібні ДВОЙНІ ЦИТИ
Sachin

1
Ви створили обмеження, використовуючи подвійні лапки, наприклад: alter table ... add constraint "Relationship143" ... "Relationship143"це справді інша назва, ніж RELATIONSHIP143. Але "RELATIONSHIP143"і RELATIONSHIP143є ідентичними
a_horse_with_no_name

2
Oracle (база даних) ніколи не створить таке ім'я, як "Relationship143"власне. Напевно, це було одним із ваших інструментів. У будь-якому випадку: як нині це відповідає, у контексті початкового запитання ваша відповідь просто неправильна.
a_horse_with_no_name
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.