我有4张桌子
customer: CustomerID - primary key, name
Magazine: name - primary key, cost, noofissues
Newspaper: name - primary key, cost, noofissues
subscription: custID - references CustomerID of Customer, name, startdate, enddate
在上文中,我可以引用name
表格中的subscription
引用name
引用Magazine
和name
引用Newspaper
吗? / p>
我创建了表格Customer
,Newspaper
和Magazine
。我只需要创建Subscription
。
答案 0 :(得分:1)
如果您询问是否可以在引用subscription
表或newspaper
表的magazine
上创建外键约束,则答案为否,您不能。外键必须只引用一个主键。
由于magazine
和newspaper
具有相同的属性集,因此简单的选项是将它们合并到一个periodical
表中,并附加periodical_type
列以指示是否这是杂志还是报纸。然后,您可以创建periodical
表的外键。
虽然在这个特定示例中可能没有意义,但您可以在subscription
中为magazine_name
和newspaper_name
添加单独的列,并在这些列上创建单独的外键约束使用check
约束确保其中一个值非NULL。如果两个不同的父表具有完全不同的属性,那么这可能是有意义的。
与您的问题无关,但作为一般建议,我不会使用name
作为主键。除了相当长,名称往往会随着时间的推移而改变,名称不一定是唯一的。我会为密钥使用不同的属性,可能是从序列生成的合成主键。
答案 1 :(得分:1)
你能做这样的事吗?
CREATE TABLE subscription (
custID INT
CONSTRAINT subscription__custid__fk REFERENCES Customer( CustomerId ),
name VARCHAR2(50)
CONSTRAINT subscription__mag_name__fk REFERENCES Magazine( Name )
CONSTRAINT subscription__news_name__fk REFERENCES Newspaper( Name ),
startdate DATE
CONSTRAINT subscription__startdate__nn NOT NULL,
enddate DATE
);
是的,你可以和同一列上有两个外键指向不同的表,但是如果列中的值是非空的,那么它将在杂志表和两个表中都有一个匹配的名称报纸桌 - 这可能不是你想要的。
你能否拥有一个外键,要求该值可以独占于该表或该表中(但不能同时存在于两个表中)?否。
但是你可以重新考虑你的数据库因此你将报纸和杂志表合并到一个表中(然后你可以轻松地参考);像这样:
CREATE TABLE customer (
CustomerID INT
CONSTRAINT customer__CustomerId__pk PRIMARY KEY,
name VARCHAR2(50)
CONSTRAINT customer__name__nn NOT NULL
);
CREATE TABLE Publications (
id INT
CONSTRAINT publications__id__pk PRIMARY KEY,
name VARCHAR2(50)
CONSTRAINT publications__name__nn NOT NULL,
cost NUMBER(6,2)
CONSTRAINT publications__cost__chk CHECK ( cost >= 0 ),
noofissues INT,
type CHAR(1),
CONSTRAINT publications__type__chk CHECK ( type IN ( 'M', 'N' ) )
);
CREATE TABLE subscription (
custID INT
CONSTRAINT subscription__custid__fk REFERENCES Customer( CustomerId ),
pubID INT
CONSTRAINT subscription__pubid__fk REFERENCES Publications( Id ),
startdate DATE
CONSTRAINT subscription__startdate__nn NOT NULL,
enddate DATE
);