为什么我一直违反了唯一约束?

时间:2018-04-08 11:41:29

标签: sql oracle

create table Doctor
(
    docID INTEGER,
    appointID INTEGER not null,
    regnum CHAR(6),   
    doc_name VARCHAR(40),
    doc_gender CHAR(1),
    qual VARCHAR(80),       

    primary key (docID),
    foreign key (appointID) references Appointment
);

INSERT INTO Doctor 
VALUES(1, 1, 'ABC001', 'Steven Arrow', 'M', 'Bachelor of Medicine  and Surgery, Deakin University, 1980');

我一直收到错误:

  

ORA-00001:违反了唯一约束(S3705969.SYS_C001160460)

我做错了什么?

4 个答案:

答案 0 :(得分:1)

这确实是重复主键值时出现的错误。解决此问题的最佳方法是使用Oracle 12C +并为主键使用生成的标识列。

一种相对简单的方法是使用序列并确保它用于所有插入

CREATE SEQUENCE doctor_sequence;

INSERT INTO Doctor( . . . )
    VALUES(doctor_sequence.enxtval, 1, 'ABC001', 'Steven Arrow', 'M', 'Bachelor of Medicine  and Surgery, Deakin University, 1980');

. . .是因为您在插入时应明确列出所有列。

我应该指出,在使用序列时,最安全的方法是使用插入触发器,因此您不依赖于应用程序逻辑来使用序列。但是,对于您正在执行的操作,可能不需要触发器。而且,如果您使用的是更新版本的Oracle,那么您只需使用生成的列。

答案 1 :(得分:1)

您应该允许Oracle使用IDENTITY填充docId列:

create table Doctor
(
docID INTEGER GENERATED ALWAYS AS IDENTITY not null ,
appointID   INTEGER ,
regnum  CHAR(6),   
doc_name    VARCHAR(40),
doc_gender  CHAR(1),
qual    VARCHAR(80),        
primary key (docID),
foreign key (appointID) references Appointment(column_name)  
);

INSERT INTO Doctor(col_names, ...)    --skip docID
VALUES( 1, 'ABC001', 'Steven Arrow', 'M',
      'Bachelor of Medicine  and Surgery, Deakin University, 1980');

答案 2 :(得分:0)

在创建表后,DB可能已经在某些列上创建了唯一约束,或者已经存在ID为1的行。您是否尝试在表中查询所有数据?如果在插入之前它是空的,则不应违反唯一约束。尝试DESCRIBE DOCTOR查看是否存在任何唯一约束。

答案 3 :(得分:0)

ORA-00001消息表示您正在向列中插入重复值。查看您的create table语句,我们可以猜测它将是DOC_ID,因此您必须已经插入了一个DOC_ID = 1的行。

那么为什么错误信息如此神秘?

  

ORA-00001:违反了唯一约束(S3705969.SYS_C001160460)

神秘的名字是因为您创建了主键而没有命名约束,因此Oracle为您生成了一个;约束不是第一类数据库对象(不像表),但它们仍然需要名称。

您可以做的是命名您创建它的约束,例如

create table Doctor
(
   docID INTEGER,
   appointID   INTEGER ,
   regnum  CHAR(6),   
   doc_name    VARCHAR(40),
   doc_gender  CHAR(1),
   qual    VARCHAR(80),        
   constraint DOCTOR_PK primary key (docID),
   constraint DOCTOR_APPOINTMENT_FK foreign key (appointID) 
        references Appointment(column_name) 
);

但如果您发现自己使用缺少名称的模式,那么您可以使用数据字典来发现正在发生的事情

select c.table_name
      , decode (c.constraint_type
                , 'P', 'Primary key'
                , 'U', 'Unique key'
                , 'R', 'Foreign key'
                , 'C', 'Check') as constraint_type
      , cc.column_name
from all_constraints c
      join all_cons_columns cc
      on cc.owner = c.owner
      and cc.table_name = c.table_name
      and cc.constraint_name = c.constraint_name
where c.owner = 'S3705969' 
and c.constraint_name = 'SYS_C001160460'
order by cc.position
/

顺便说一下,你的外键似乎是错误的方式。一位医生有很多约会,因此您的APPOINTMENT表应该有一个DOCTOR_ID列,其中一个外键引用了DOCTOR表。