テーブルに新しい行を作成しようとしています。テーブルには2つの制約があります。1つはキーフィールド(DB_ID)に、もう1つは値をいくつかのフィールドENVのいずれかに制約します。挿入を行うときに、キーフィールドを挿入しようとしているフィールドの1つとして含めませんが、このエラーが発生します。
unique constraint (N390.PK_DB_ID) violated
エラーの原因となるSQLは次のとおりです。
insert into cmdb_db
(narrative_name, db_name, db_type, schema, node, env, server_id, state, path)
values
('Test Database', 'DB', 'TYPE', 'SCH', '', 'SB01', 381, 'TEST', '')
私が見つけた唯一のことは、行が手動で挿入された場合、Oracleがすでに使用中のDB_IDを割り当てようとしている可能性です。このデータベースのデータは、本番データベースから何らかの形で復元/移動されましたが、その方法に関する詳細はわかりません。
何かご意見は?
おそらく、DB_ID
列に値を指定していないため、その値は、テーブルで定義された挿入トリガーの前に行レベルで設定されています。そのトリガーは、おそらく、シーケンスから値を選択することです。
データは(おそらく最近)実稼働データベースから移動されたため、私の賭けは、データがコピーされたときに、シーケンスも変更されなかったことです。シーケンスは、現在エラーの原因となっているテーブルにある最大のDB_ID
よりもはるかに低い値を生成していると思います。
この疑いを確認するには、トリガーを見てどのシーケンスが使用されているかを判断し、
SELECT <<sequence name>>.nextval
FROM dual
そしてそれを比較する
SELECT MAX(db_id)
FROM cmdb_db
私が疑うように、シーケンスがデータベースに既に存在する値を生成している場合、未使用の値を生成するまでシーケンスをインクリメントするか、INCREMENT
を非常に大きな値に設定するように変更できます。 nextvalを1回、INCREMENT
を1に戻します。
主キーフィールドDB_IDの値を指定していないようです。それが主キーである場合、その列に一意の値を指定する必要があります。それを提供しない唯一の方法は、挿入時に値を提供するデータベーストリガーを作成することです。ほとんどの場合、シーケンスから派生します。
これが別のデータベースからの復元であり、この新しいインスタンスにシーケンスがある場合、値を再利用しようとしている可能性があります。古いデータに1〜1000の一意のキーがあり、現在のシーケンスが500である場合、既存の値が生成されます。このテーブルにシーケンスが存在し、それを使用しようとしている場合、テーブルの値をシーケンスの現在の値と調整する必要があります。
SEQUENCE_NAME.CURRVALを使用して、シーケンスの現在の値を確認できます(もちろん存在する場合)
エラーは、DB内の既存の主キーを複製しているようです。 IDENTITYキーワードなどを使用して、SQLコードを変更して独自のプライマリキーを実装する必要があります。
CREATE TABLE [DB] (
[DBId] bigint NOT NULL IDENTITY,
...
CONSTRAINT [DB_PK] PRIMARY KEY ([DB] ASC),
);