如何在SQL中引用复合主键

时间:2017-09-28 08:37:07

标签: sql oracle foreign-keys constraints composite-primary-key

我使用以下代码创建了以下3个表。

CREATE TABLE BUILDING(
BUILDINGNO CHAR(2),
BUILDINGWING VARCHAR2(15),
BUILDINGLANE VARCHAR2(15),
CONSTRAINT BUILDING_PK PRIMARY KEY(BUILDINGNO));

CREATE TABLE ROOM(
BUILDINGNO CHAR(2),
ROOMNO CHAR(2),
ROOMCAPACITY NUMBER(3),
CONSTRAINT ROOM_PK PRIMARY KEY(BUILDINGNO,ROOMNO),
CONSTRAINT ROOM_FK1 FOREIGN KEY(BUILDINGNO) REFERENCES BUILDING(BUILDINGNO));

CREATE TABLE SPEAKER(
SPEAKERID CHAR(2),
SPEAKERNAME VARCHAR2(20),
SPEAKERADDRESS VARCHAR2(50),
SPEAKERPHONE CHAR(12),
CONSTRAINT SPEAKER_PK PRIMARY KEY(SPEAKERID));

我需要创建的第4个表是这样的。

CREATE TABLE CONFERENCESESSION(
SESSIONID CHAR(4),
BUILDINGNO CHAR(2),
ROOMNO CHAR(2),
SPEAKERID CHAR(2),
SESSIONDATE DATE,
SESSIONPRICE NUMBER(4,2),
CONSTRAINT SESSION_PK PRIMARY KEY(SESSIONID),
CONSTRAINT SESSION_FK1 FOREIGN KEY(BUILDINGNO) REFERENCES BUILDING(BUILDINGNO),
CONSTRAINT SESSION_FK2 FOREIGN KEY(ROOMNO) REFERENCES ROOM(ROOMNO),
CONSTRAINT SESSION_FK3 FOREIGN KEY(SPEAKERID) REFERENCES SPEAKER(SPEAKERID));

但是我知道FK2 ROOMNO(第二行的第二行)的约束是不正确的,因为ROOM表中的PK是BUILDINGNO,ROOMNO。 用于此行的正确代码是什么?

2 个答案:

答案 0 :(得分:1)

我们声明一个SQL FK(FOREIGN KEY)约束,表示列列表的子行总是出现在其他位置,作为构成SQL PK(PRIMARY KEY)或UNIQUE NOT NULL的列列表的子行值。在其他声明未暗示的情况下声明它。它必须在声明的SQL PK(PRIMARY KEY)或UNIQUE NOT NULL中引用列列表。因此,您必须在引用的表中声明,即使NOT NULL已经暗示了这一点,并且包含较小的PK或UNIQUE NOT NULL。

所以请注意,SQL PK不一定是关系意义上的PK唯一但不包含较小的唯一列集,即不是包含较小的超级密钥的超级密钥,即是最小/不可简化的超级密钥,即一个CK(候选键)。

在这里,您可能需要替换buildingno& roomno FK为一,(buildingno, roomno)Room

CONSTRAINT SESSION_FK12
    FOREIGN KEY(BUILDINGNO,ROOMNO) REFERENCES ROOM(BUILDINGNO,ROOMNO)

可能适合表格的含义 - 事实上你不会给予,所以我们无法知道,我们只能猜测。例如,如果buildingno 在房间中声明PK或UNIQUE NOT NULL,那么当roomno IS NOT NULL实际上与(buildingno, roomno)一致并暗示Room时,可以声明为PK或UNIQUE NOT NULL,也许你的FK 正确,但你的buildingno声明不合适。

当列列表的子行值始终显示在其他位置作为名为IND(包含依赖项)约束的列列表的子行值时。没有办法在SQL中声明非FK IND;我们必须通过触发器强制执行。 可能就是您的设计所需要的。

您可以将FK从Building保留到buildingno,但我建议的FK和Room {F} Building中的FK暗示{ {1}}。

referencing part of the composite primary key

答案 1 :(得分:0)

正如我们在documentation中看到的,我们可以创建复合外键:

CREATE TABLE CONFERENCESESSION ...
...
CONSTRAINT SESSION_FK2 
    FOREIGN KEY(BUILDINGNO, ROOMNO) 
    REFERENCES ROOM(BUILDINGNO, ROOMNO),
...

测试:

insert into building values (1, null, null);
insert into room values (1, 1, null);
insert into speaker (speakerid) values (1);
insert into conferencesession (sessionid,buildingno,roomno,speakerid) values (1, 1, 1, 1);
insert into conferencesession (sessionid,buildingno,roomno,speakerid) values (2, 1, 2, 1);

上次插入会产生错误ORA-02291