我使用以下代码创建了以下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。 用于此行的正确代码是什么?
答案 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}}。
答案 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
。