我正在尝试在表格中创建一个新行。表上有两个约束 - 一个在关键字段(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。此数据库中的数据以某种方式从生产数据库中恢复/移动,但我没有详细说明如何完成。
有什么想法吗?
答案 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),
);