SQL错误'未找到父密钥'不正确使用的外键?

时间:2018-05-19 05:49:19

标签: sql oracle foreign-keys

我更新了我的尝试,保留了一些像CHAR一样的东西,但仍然得到类似的错误:第1行的错误: ORA-02091:交易回滚 ORA-02291:违反了完整性约束(MMM1339.ITEMNO_PHAR_FK) - 未找到父密钥

申请单的外键在不同的供应主键中都有值,所以我不确定为什么还有问题。

CREATE TABLE SUPPLIER
(SUPPLIERNO   CHAR(6),
 SUPPLIERNAME VARCHAR2(100),
 PHONENO VARCHAR2(12),
 ADDRESS VARCHAR(100),
 FAXNO VARCHAR(12),
 CONSTRAINT SUPPLIERNO_SSPL_PK PRIMARY KEY(SUPPLIERNO));

CREATE TABLE SUPPLIES_PHARMACEUTICAL
(ITEMNO         CHAR(6),
SUPPLIERNO      CHAR(6),
NAME            VARCHAR2(25),
DESCRIPTION     VARCHAR2(25),
QUANTITYINSTOCK INT,
REORDERLEVEL    INT,
COSTPERUNIT     DECIMAL(6,2),
DOSAGE          VARCHAR2(12),
CONSTRAINT ITEMNO_PHAR_PK PRIMARY KEY(ITEMNO));

CREATE TABLE SUPPLIES_SURGICAL
(ITEMNO         CHAR(6),
NAME            VARCHAR2(25),
DESCRIPTION     VARCHAR2(25),
QUANTITYINSTOCK INT,
REORDERLEVEL    INT,
COSTPERUNIT     DECIMAL(6,2),
SUPPLIERNO      CHAR(6),
CONSTRAINT ITEMNO_SUP_PK PRIMARY KEY(ITEMNO));

CREATE TABLE SUPPLIES_NONSURGICAL
(ITEMNO         CHAR(6),
NAME            VARCHAR2(25),
DESCRIPTION     VARCHAR2(25),  
QUANTITYINSTOCK INT,
REORDERLEVEL    INT,
COSTPERUNIT     DECIMAL(6,2),
SUPPLIERNO      CHAR(6),
CONSTRAINT ITEMNO_NONSURG_PK PRIMARY KEY(ITEMNO));

CREATE TABLE STAFF_CHARGENURSE
(STAFFNO   CHAR(6),
 ADDRESS   VARCHAR2(25),
 POSITION  VARCHAR2(12),
 BUDGET    DECIMAL(6,2),
 SPECIALTY VARCHAR2(12),
 CONSTRAINT STAFFNO_CHNURSE_PK PRIMARY KEY(STAFFNO));

 CREATE TABLE REQUISITION
 (REQNO CHAR(6),
  STAFFNO CHAR(6),
  STAFFNAME VARCHAR2(25),
  WARDNO CHAR(6),
  ITEMNO CHAR(6),
  QUANTITY INT,
  DATEORDERED DATE,
  DATERECIEVED DATE,
  CONSTRAINT REQ_PK PRIMARY KEY(REQNO));

 ALTER TABLE SUPPLIES_PHARMACEUTICAL ADD CONSTRAINT SUPPLIERNO_PHA_FK FOREIGN KEY(SUPPLIERNO) REFERENCES SUPPLIER(SUPPLIERNO) DEFERRABLE INITIALLY DEFERRED;
 ALTER TABLE SUPPLIES_SURGICAL ADD CONSTRAINT SUPPLIERNO_SURG_FK FOREIGN KEY(SUPPLIERNO) REFERENCES SUPPLIER(SUPPLIERNO) DEFERRABLE INITIALLY DEFERRED;
 ALTER TABLE SUPPLIES_NONSURGICAL ADD CONSTRAINT SUPPLIERNO_NONSURG_FK FOREIGN KEY(SUPPLIERNO) REFERENCES SUPPLIER(SUPPLIERNO) DEFERRABLE INITIALLY DEFERRED;
 ALTER TABLE REQUISITION ADD CONSTRAINT STAFFNO_REQ_FK FOREIGN KEY(STAFFNO) REFERENCES STAFF_CHARGENURSE(STAFFNO) DEFERRABLE INITIALLY DEFERRED;
 ALTER TABLE REQUISITION ADD CONSTRAINT ITEMNO_PHAR_FK FOREIGN KEY(ITEMNO) REFERENCES SUPPLIES_PHARMACEUTICAL(ITEMNO) DEFERRABLE INITIALLY DEFERRED;
 ALTER TABLE REQUISITION ADD CONSTRAINT ITEMNO_SURG_FK FOREIGN KEY(ITEMNO) REFERENCES SUPPLIES_SURGICAL(ITEMNO) DEFERRABLE INITIALLY DEFERRED;
 ALTER TABLE REQUISITION ADD CONSTRAINT ITEMNO_NONSURG_FK FOREIGN KEY(ITEMNO) REFERENCES SUPPLIES_NONSURGICAL(ITEMNO) DEFERRABLE INITIALLY DEFERRED;

 INSERT INTO REQUISITION VALUES('000001', '345000', 'Julie Wood', '8', '888520', 2, '27-FEB-2018', '15-MAR-2018');
 INSERT INTO REQUISITION VALUES('000002', '345000', 'Julie Wood', '8', '923956', 1, '25-FEB-2018', '28-FEB-2018');
 INSERT INTO REQUISITION VALUES('000003', '345000', 'Julie Wood', '8', '054802', 3, '20-FEB-2018', '22-FEB-2018');

 INSERT INTO SUPPLIES_PHARMACEUTICAL VALUES ('823456', '100001', 'Zanax', 'Anti Depressant', 8, 2, 100.50, '50mg');
 INSERT INTO SUPPLIES_PHARMACEUTICAL VALUES ('923956', '100001', 'Zupridol', 'Blood Pressure Treatment', 12, 5, 50, '20mg');
 INSERT INTO SUPPLIES_PHARMACEUTICAL VALUES ('003952', '200001', 'Amibreezax', 'Antifungal Ear Wax', 2, 1, 200, '5g');
 INSERT INTO SUPPLIES_PHARMACEUTICAL VALUES ('004955', '200001', 'Ambridax', 'Blood Fungus Treatment', 5, 10, 20, '2mg');

 INSERT INTO SUPPLIES_SURGICAL VALUES ('054802', 'Scalpel', 'Scalping Tool', 20, 10, 200.42, '100001');
 INSERT INTO SUPPLIES_SURGICAL VALUES ('634520', 'Stitches', 'Suture Tool', 100, 10, 2.50, '200001');

 INSERT INTO SUPPLIES_NONSURGICAL VALUES ('888520', 'Cart', '5ftx2ftx3ft', 2, 0, 200.00, '100001');
 INSERT INTO SUPPLIES_NONSURGICAL VALUES ('000423', 'Tool Holder', 'Holds Inspection Equip.', 4, 2, 50.00, '100001');

 INSERT INTO STAFF_CHARGENURSE VALUES('345000', '32 Stark St. Portland, OR', 'Charge Nurse', 8000.99, 'Head Trauma');
 INSERT INTO STAFF_CHARGENURSE VALUES('246000', '18 Wilson Rd Portland, OR', 'Charge Nurse', 6000, 'Epidermus');

 INSERT INTO SUPPLIER VALUES ('100001','Company A', '503-222-3333', '100 SE Stark Rd Portland, OR', '503-666-4444');
 INSERT INTO SUPPLIER VALUES ('200001','Company B', '666-333-4444', '500 SE Bilerica Rd Akron, OH', '666-444-3333');

 COMMIT;

4 个答案:

答案 0 :(得分:1)

编辑:

SUPPLIES_SURGICALSUPPLIES_NONSURGICAL合并为一个SUPPLIES表,并将PHARMA_DOSAGE定义为其下的子表。

现在SUPPLIES行必须是手术或非手术,可以实现为Y / N标志并由检查约束强制执行。 (但是,一个可能的问题是,该模型不会阻止您为手术项目添加剂量。)

在下文中,我已将ITEMNO设为整数并修正了CHAR列。您可以考虑查看以NO结尾的所有列的数据类型,特别是如果它们将按顺序生成。我还会生成所有生成的PK列标识列,但我会将详细信息留给您。

create table supplier
( supplierno      integer primary key );

create table supplies
( itemno          integer
                  constraint supplies_pk primary key
, supplierno      constraint supplies_supplier_fk references supplier(supplierno)
, name            varchar2(25) not null
, description     varchar2(25) null
, quantityinstock integer
, reorderlevel    integer
, costperunit     number(6,2)
, is_surgical     varchar2(1) not null
                  constraint supplies_surgical_yn_chk check(is_surgical in ('Y','N')) );

create table pharma_dosage
( itemno          constraint pharma_supplies_fk references supplies(itemno)
                  constraint pharma_supplies_pk primary key
, dosage          varchar2(12) not null );

create table staff_chargenurse
( staffno         varchar2(6)
                  constraint staffno_chnurse_pk primary key
, address         varchar2(25)
, position        varchar2(12)
, budget          number(6,2)
, specialty       varchar2(12) );

create table requisition
( reqno           varchar2(6)
                  constraint reqno_pk primary key
, staffno         constraint staffno_req_fk references staff_chargenurse(staffno)
, staffname       varchar2(25)
, wardno          varchar2(6)
, itemno          constraint itemno_supplies_fk references supplies(itemno)
, quantity        integer
, dateordered     date
, daterecieved    date );

insert into supplier values ('100001');
insert into supplier values ('200001');

insert into supplies (itemno, supplierno, name, description, quantityinstock, reorderlevel, costperunit, is_surgical) values (823456, '100001', 'Zanax', 'Anti Depressant', 8, 2, 100.50, 'N');
insert into supplies (itemno, supplierno, name, description, quantityinstock, reorderlevel, costperunit, is_surgical) values (923956, '100001', 'Zupridol', 'Blood Pressure Treatment', 12, 5, 50, 'N');
insert into supplies (itemno, supplierno, name, description, quantityinstock, reorderlevel, costperunit, is_surgical) values (003952, '200001', 'Amibreezax', 'Antifungal Ear Wax', 2, 1, 200, 'N');
insert into supplies (itemno, supplierno, name, description, quantityinstock, reorderlevel, costperunit, is_surgical) values (004955, '200001', 'Ambridax', 'Blood Fungus Treatment', 5, 10, 20, 'N');

insert into pharma_dosage (itemno, dosage) values (823456, '50mg');
insert into pharma_dosage (itemno, dosage) values (923956, '20mg');
insert into pharma_dosage (itemno, dosage) values (003952, '5g');
insert into pharma_dosage (itemno, dosage) values (004955, '2mg');

insert into supplies (itemno, name, description, quantityinstock, reorderlevel, costperunit, supplierno, is_surgical) values (054802, 'Scalpel', 'Scalping Tool', 20, 10, 200.42, '100001', 'Y');
insert into supplies (itemno, name, description, quantityinstock, reorderlevel, costperunit, supplierno, is_surgical) values (634520, 'Stitches', 'Suture Tool', 100, 10, 2.50, '200001', 'Y');

insert into supplies (itemno, name, description, quantityinstock, reorderlevel, costperunit, supplierno, is_surgical) values (888520, 'Cart', '5ftx2ftx3ft', 2, 0, 200.00, '100001', 'N');
insert into supplies (itemno, name, description, quantityinstock, reorderlevel, costperunit, supplierno, is_surgical) values (000423, 'Tool Holder', 'Holds Inspection Equip.', 4, 2, 50.00, '100001', 'N');

insert into staff_chargenurse values('345000', '32 Stark St. Portland, OR', 'Charge Nurse', 8000.99, 'Head Trauma');
insert into staff_chargenurse values('246000', '18 Wilson Rd Portland, OR', 'Charge Nurse', 6000, 'Epidermus');

insert into requisition (reqno, staffno, staffname, wardno, itemno, quantity, dateordered, daterecieved) values('000001', '345000', 'Julie Wood', '8', 888520, 2, date '2018-02-27', date '2018-03-15');
insert into requisition (reqno, staffno, staffname, wardno, itemno, quantity, dateordered, daterecieved) values('000002', '345000', 'Julie Wood', '8', 823456, 1, date '2018-02-25', date '2018-02-28');
insert into requisition (reqno, staffno, staffname, wardno, itemno, quantity, dateordered, daterecieved) values('000003', '345000', 'Julie Wood', '8', 054802, 3, date '2018-02-20', date '2018-02-22');

答案 1 :(得分:1)

不幸的是(对于你的DDL代码)我必须同意@William Robertson - 你需要改变你的模型,因此,你需要完全重写你的DDL代码。原因如下:

从原始的DDL代码看一个反向工程模型,我们可以看到REQUISITION有3个(抱歉,4个)父表。这就是为什么它的插入总是因外键违规而失败的原因。你的模特:

enter image description here

以DDL代码的形式说明问题的简化示例可能如下所示:

create table parent1 ( id number primary key ) ; -- analogy: supplies_pharmaceutical
create table parent2 ( id number primary key ) ; -- analogy: supplies_nonsurgical
create table parent3 ( id number primary key ) ; -- analogy: supplies_surgical

create table child ( -- analogy: requisitions
  id number primary key
, parentid number 
);

alter table child add constraint fkey_parent1
foreign key ( parentid ) references parent1 ( id ) ;

alter table child add constraint fkey_parent2
foreign key ( parentid ) references parent2 ( id ) ;

alter table child add constraint fkey_parent3
foreign key ( parentid ) references parent3 ( id ) ;

begin
  insert into parent1 ( id ) values ( 1 ) ;
  insert into parent2 ( id ) values ( 2 ) ;
  insert into parent3 ( id ) values ( 3 ) ;
end ;
/

因此,填充我们的父表后,只需快速检查:

select 'parent1 (id) -> ' || id from parent1
union all
select 'parent2 (id) -> ' ||  id from parent2
union all
select 'parent3 (id) -> ' ||  id from parent3
;

-- result
'PARENT1(ID)->'||ID  
parent1 (id) -> 1    
parent2 (id) -> 2    
parent3 (id) -> 3 

一切都好。现在我们想在子表中插入一些行。

insert into child ( id, parentid ) values ( 100, 1 ) ;
-- ORA-02291: integrity constraint (...FKEY_PARENT3) violated - parent key not found

insert into child ( id, parentid ) values ( 101, 2 ) ;
-- ORA-02291: integrity constraint (...FKEY_PARENT3) violated - parent key not found

insert into child ( id, parentid ) values ( 102, 3 ) ;
-- ORA-02291: integrity constraint (...FKEY_PARENT2) violated - parent key not found

您会看到正确的父表不仅仅是“自动选择”。

在William的模型OTOH中,REQUISITION只有一个父母(表)与“供应”有关。哪个应该使插入行更容易...见下文。

enter image description here

答案 2 :(得分:0)

我们需要一些重新排列来抑制 ORA-02291 错误:

  • 首先, INSERT 语句应以#结束 分号。
  • 应该存在一个名为 SUPPLIER 的表来引用。
  • 创建没有 FOREIGN KEYS 的表格,并在创建所有表格之后, ALTER 表包含 FOREIGN KEYS 。 为了在INSERT操作期间抑制数据不一致,我们需要创建 FOREIGN KEYS 作为 DEFERRABLE INITIALLY DEFERRED (通过以下方式,我们不会遇到任何错误,即使在结束COMMIT发布)。

    我认为,您最好将 SUPPLIERNO 列存储为 INT(EGER) NUMBER ,而不是 CHAR 。此外,不推荐使用 CHAR 数据类型,最好将它们转换为 VARCHAR2

因此,请使用以下一系列操作(在底部,我更改了 REQUISITION 的某些值,以免违反外部约束):

    CREATE TABLE SUPPLIER
    (SUPPLIERNO   INT,
     SUPPLIERNAME VARCHAR2(100),
     CONSTRAINT SUPPLIERNO_SSPL_PK PRIMARY KEY(SUPPLIERNO));

    CREATE TABLE SUPPLIES_PHARMACEUTICAL
    (ITEMNO         INT,
    SUPPLIERNO      INT,
    NAME            VARCHAR2(25),
    DESCRIPTION     VARCHAR2(25),
    QUANTITYINSTOCK INT,
    REORDERLEVEL    INT,
    COSTPERUNIT     DECIMAL(6,2),
    DOSAGE          VARCHAR2(12),
    CONSTRAINT ITEMNO_PHAR_PK PRIMARY KEY(ITEMNO));

    CREATE TABLE SUPPLIES_SURGICAL
    (ITEMNO         INT,
    NAME            VARCHAR2(25),
    DESCRIPTION     VARCHAR2(25),
    QUANTITYINSTOCK INT,
    REORDERLEVEL    INT,
    COSTPERUNIT     DECIMAL(6,2),
    SUPPLIERNO      INT,
    CONSTRAINT ITEMNO_SUP_PK PRIMARY KEY(ITEMNO));

    CREATE TABLE SUPPLIES_NONSURGICAL
    (ITEMNO         INT,
    NAME            VARCHAR2(25),
    DESCRIPTION     VARCHAR2(25),  
    QUANTITYINSTOCK INT,
    REORDERLEVEL    INT,
    COSTPERUNIT     DECIMAL(6,2),
    SUPPLIERNO      INT,
    CONSTRAINT ITEMNO_NONSURG_PK PRIMARY KEY(ITEMNO));

    CREATE TABLE STAFF_CHARGENURSE
    (STAFFNO   INT,
     ADDRESS   VARCHAR2(25),
     POSITION  VARCHAR2(12),
     BUDGET    DECIMAL(6,2),
     SPECIALTY VARCHAR2(12),
     CONSTRAINT STAFFNO_CHNURSE_PK PRIMARY KEY(STAFFNO));

     ALTER TABLE SUPPLIES_PHARMACEUTICAL ADD CONSTRAINT SUPPLIERNO_PHA_FK FOREIGN KEY(SUPPLIERNO) REFERENCES SUPPLIER(SUPPLIERNO) DEFERRABLE INITIALLY DEFERRED;
     ALTER TABLE SUPPLIES_SURGICAL ADD CONSTRAINT SUPPLIERNO_SURG_FK FOREIGN KEY(SUPPLIERNO) REFERENCES SUPPLIER(SUPPLIERNO) DEFERRABLE INITIALLY DEFERRED;
     ALTER TABLE SUPPLIES_NONSURGICAL ADD CONSTRAINT SUPPLIERNO_NONSURG_FK FOREIGN KEY(SUPPLIERNO) REFERENCES SUPPLIER(SUPPLIERNO) DEFERRABLE INITIALLY DEFERRED;

     INSERT INTO SUPPLIES_PHARMACEUTICAL VALUES (888520, 100001, 'Zanax', 'Anti Depressant', 8, 2, 100.50, '50mg');
     INSERT INTO SUPPLIES_PHARMACEUTICAL VALUES (923956, 100001, 'Zupridol', 'Blood Pressure Treatment', 12, 5, 50, '20mg');
     INSERT INTO SUPPLIES_PHARMACEUTICAL VALUES (634520, 200001, 'Amibreezax', 'Antifungal Ear Wax', 2, 1, 200, '5g');
     INSERT INTO SUPPLIES_PHARMACEUTICAL VALUES (4955, 200001, 'Ambridax', 'Blood Fungus Treatment', 5, 10, 20, '2mg');

     INSERT INTO SUPPLIES_SURGICAL VALUES (888520, 'Scalpel', 'Scalping Tool', 20, 10, 200.42, 100001);
     INSERT INTO SUPPLIES_SURGICAL VALUES (634520, 'Stitches', 'Suture Tool', 100, 10, 2.50, 200001);

     INSERT INTO SUPPLIES_NONSURGICAL VALUES (888520, 'Cart', '5ftx2ftx3ft', 2, 0, 200.00, 100001);
     INSERT INTO SUPPLIES_NONSURGICAL VALUES (634520, 'Tool Holder', 'Holds Inspection Equip.', 4, 2, 50.00, 100001);


     INSERT INTO STAFF_CHARGENURSE VALUES(345000, '32 Stark St. Portland, OR', 'Charge Nurse', 8000.99, 'Head Trauma');
     INSERT INTO STAFF_CHARGENURSE VALUES(246000, '18 Wilson Rd Portland, OR', 'Charge Nurse', 6000, 'Epidermus');

     INSERT INTO SUPPLIER VALUES (100001,'Company A');
     INSERT INTO SUPPLIER VALUES (200001,'Company B');

     CREATE TABLE REQUISITION
     (REQNO       INT,
     STAFFNO      INT,
     STAFFNAME    VARCHAR2(25),
     WARDNO       INT,
     ITEMNO       INT,
     QUANTITY     INT,
     DATEORDERED  DATE,
     DATERECIEVED DATE,
     CONSTRAINT REQNO_PK PRIMARY KEY(REQNO),
     CONSTRAINT STAFFNO_REQ_FK FOREIGN KEY(STAFFNO) REFERENCES STAFF_CHARGENURSE(STAFFNO),
     CONSTRAINT ITEMNO_PHAR_FK FOREIGN KEY(ITEMNO) REFERENCES SUPPLIES_PHARMACEUTICAL(ITEMNO),
     CONSTRAINT ITEMNO_SURG_FK FOREIGN KEY(ITEMNO) REFERENCES SUPPLIES_SURGICAL(ITEMNO),
     CONSTRAINT ITEMNO_NONSURG_FK FOREIGN KEY(ITEMNO) REFERENCES SUPPLIES_NONSURGICAL(ITEMNO));
     INSERT INTO REQUISITION VALUES(1, 345000, 'Julie Wood', 8, 888520, 2, '27-FEB-2018', '15-MAR-2018');
     INSERT INTO REQUISITION VALUES(2, 345000, 'Julie Wood', 8, 634520, 1, '25-FEB-2018', '28-FEB-2018');
     INSERT INTO REQUISITION VALUES(3, 345000, 'Julie Wood', 8, 634520, 3, '20-FEB-2018', '22-FEB-2018');

     COMMIT;          

答案 3 :(得分:0)

这个答案与你的问题有关,为什么你的延迟约束的更新定义仍然会导致FK违规。

在尝试提交之前插入行之后:

n_estimators

select r.reqno, r.itemno , sp.name as pharmaceutical , ss.name as surgical , sn.name as nonsurgical from requisition r left join supplies_pharmaceutical sp on sp.itemno = r.itemno left join supplies_surgical ss on ss.itemno = r.itemno left join supplies_nonsurgical sn on sn.itemno = r.itemno; REQNO ITEMNO PHARMACEUTICAL SURGICAL NONSURGICAL ------- ------- --------------- --------------- --------------- 000001 888520 Cart 000002 923956 Zupridol 000003 054802 Scalpel 违反了约束888520,因为它未在父表ITEMNO_PHAR_FK中定义:

SUPPLIES_PHARMACEUTICAL

它也违反了ALTER TABLE REQUISITION ADD CONSTRAINT ITEMNO_PHAR_FK FOREIGN KEY(ITEMNO) REFERENCES SUPPLIES_PHARMACEUTICAL(ITEMNO) ... ,因为ITEMNO_SURG_FK不在父表888520中:

SUPPLIES_SURGICAL

等等。每个申请行违反了两个约束。将约束定义为延迟不会改变除错误时间之外的任何内容。

为了满足您的FK定义,每个itemno都需要存在于所有三个耗材表中。

如果您确实需要三个耗材表,则需要三个独立的耗材列,每个列都有自己的FK到相应的表。

(你真的应该将那些ALTER TABLE REQUISITION ADD CONSTRAINT ITEMNO_SURG_FK FOREIGN KEY(ITEMNO) REFERENCES SUPPLIES_SURGICAL(ITEMNO) ... 列更改为标准字符串类型。CHAR在Oracle数据库中没有位置,它纯粹是出于奇怪的可移植性和ANSI完整性要求,而不是你的类型实际上应该使用。)