存在しない制約を削除することも、作成することもできません


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コマンドは正常に機能しましたが、ADDコマンドは失敗しました。今、私は悪循環に陥っている。制約が存在しないため、制約を削除できません(最初の削除は期待どおりに機能しました)。

ORA-02443:制約を削除できません-存在しない制約

名前が既に存在するため、作成できません。

ORA-00955:名前は既存のオブジェクトですでに使用されています

私は型A_DUP_CALLE_UK1SQL開発者に検索それがある...箱や!所有者、テーブル名、tablescape ...すべての試合:それは、同じ名前を持つ別のオブジェクトではありません、私の元の制約。テーブルは制約の詳細に表示されますが、制約はテーブルの詳細に表示されません。

私の質問:

  • これの説明は何ですか?
  • ライブサーバーで実際のアップグレードを行ったときに、それが起こらないようにするにはどうすればよいですか?

(サーバーは10g XEです。タグを作成するのに十分な評判がありません。)


ユニーク制約ではなく、他のタイプのオブジェクトとして作成されたのでしょうか?多分ユニークなインデックス..
マリアン

テーブル名を引用符で囲んで最初の作成を実行できましたか?これにより、名前の大文字と小文字が区別されます。もしそうなら、引用符と同じケースでドロップすることができます。
アダムバトラー

回答:


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は2つのオブジェクトを作成します。「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が作成されることがあります。その場合、ドロップするときに制約名を二重引用符で囲む必要があります。
サチン14

そしてそれは私のために働いた。制約に明示的に名前を付けていなかったため、システムはそれを独自の生成名にし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

2
Oracle(データベース)が独自の名前を作成することはありません"Relationship143"。これはおそらくあなたのツールの1つでした。とにかく、現状では、あなたの答えは元の質問の文脈では単純に間違っています。
a_horse_with_no_name 14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.