插入期间唯一的约束违规:为什么? (Oracle)的

时间:2011-09-27 14:57:17

标签: oracle unique-constraint

我正在尝试在表格中创建一个新行。表上有两个约束 - 一个在关键字段(DB_ID)上,另一个约束一个值为字段ENV中的几个之一。当我执行插入操作时,我不会将键字段包含为我要插入的字段之一,但我收到此错误:

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。此数据库中的数据以某种方式从生产数据库中恢复/移动,但我没有详细说明如何完成。

有什么想法吗?

3 个答案:

答案 0 :(得分:39)

据推测,由于您没有为DB_ID列提供值,因此该值将在表上定义的插入触发器之前由行级填充。据推测,该触发器是从序列中选择值。

由于数据是从生产数据库中移动的(大概是最近的),我的赌注是当复制数据时,序列也没有被修改。我猜这个序列生成的值远远低于当前表中导致错误的最大DB_ID

您可以通过查看触发器以确定正在使用哪个序列并执行

来确认此怀疑
SELECT <<sequence name>>.nextval
  FROM dual

并将其与

进行比较
SELECT MAX(db_id)
  FROM cmdb_db

如果我怀疑序列正在生成数据库中已存在的值,则可以递增序列,直到它生成未使用的值,或者您可以更改它以将INCREMENT设置为非常大的值,获取nextval一次,并将INCREMENT设置为1。

答案 1 :(得分:1)

看起来您没有为主键字段DB_ID提供值。如果这是主键,则必须为该列提供唯一值。不提供它的唯一方法是创建一个数据库触发器,在插入时,它将提供一个值,很可能是从序列派生的。

如果这是从另一个数据库恢复,并且在这个新实例上有一个序列,它可能正在尝试重用一个值。如果旧数据具有1 - 1000的唯一键,并且当前序列为500,则它将生成已存在的值。如果此表存在一个序列并且它正在尝试使用它,则需要将表中的值与序列的当前值进行协调。

您可以使用SEQUENCE_NAME.CURRVAL查看序列的当前值(如果它当然存在)

答案 2 :(得分:1)

您的错误看起来像是在复制数据库中已存在的主键。您应该使用类似IDENTITY关键字的内容修改您的sql代码以实现自己的主键。

CREATE TABLE [DB] (
    [DBId] bigint NOT NULL IDENTITY,
    ...

    CONSTRAINT [DB_PK] PRIMARY KEY ([DB] ASC),

);