我有一个没有自然主键的实体。唯一行由三列标识,其中任何一列都可以具有唯一值,其他列将为空。为了一个假想的例子,这里是我的实体:
-------- Product -------- Shelf Order Customer Category --------
只有货架或客户订单或类别列中的一个将具有填充值,可能具有ID(不会是另一个表中的FK)。如何为它设计一张table?我只需要在这些列上标识唯一的行。我使用Oracle DB,如果它有帮助。
o4tp2gmn1#
你很可能不能。唯一行由三列标识,其中任何一列都可以具有唯一值,其他列将为空。这是一个“showstopper”。虽然你可以在这4列上创建唯一的组合键,但在你尝试插入另一个已经包含该组合的行之前,一切都没有问题。举例来说:
SQL> create table product 2 (shelf number, 3 c_order number, 4 customer number, 5 category number, 6 -- 7 constraint uk_product unique (shelf, c_order, customer, category) 8 ); Table created. SQL> insert into product (shelf, c_order, customer, category) values (1, null, null, null); 1 row created. SQL> insert into product (shelf, c_order, customer, category) values (2, null, 8, null); 1 row created. SQL> insert into product (shelf, c_order, customer, category) values (1, null, 4, null); 1 row created. SQL> insert into product (shelf, c_order, customer, category) values (1, null, null, null); insert into product (shelf, c_order, customer, category) values (1, null, null, null) * ERROR at line 1: ORA-00001: unique constraint (SCOTT.UK_PRODUCT) violated
此行失败,因为这样的组合已经存在(这是我插入的第一行)。如果你同意的话--我的意思是,你真的希望这样的事情发生--那么它会起作用的。如果不是,就不会。
mu0hgdu02#
您可以通过创建唯一约束(而不是主键)来实现此目的。唯一约束允许它们的列成员可以为NULL,将NULL视为一个独特的值。这在可空列是某种状态/货币的指示符时特别有用(例如,NULL end_date可以表示历史类型2表中的当前活动行,并且该约束强制任何实体都不具有多于一个NULL end_date,即多于一个活动/当前行)。如果你想创建一个约束,你会说:
end_date
constraint uq_product unique ("Shelf","Order","Customer","Category")
然而,你的特殊情况并不适合这样做。老实说,我无法想象为什么你会有一个设计,其中 shelf,order,customer 和 category 都是空的,也不能想象为什么你只在其中一个中有一个标识值,也不能想象为什么具有标识值的列会四处移动。除了 order 之外,所有这些听起来都不像是一个识别列,也不像是它们的组合。如果其中只有一个值,而其他值都没有,这是没有意义的。这是一个明确的设计缺陷,应该通过重新设计表来纠正。要么纠正您的设计,使您有一个适当的标识键,或者干脆不尝试创建任何类型的键。表不必有约束。但我怀疑你可能应该修改设计,这样你就可以。
2条答案
按热度按时间o4tp2gmn1#
你很可能不能。
唯一行由三列标识,其中任何一列都可以具有唯一值,其他列将为空。
这是一个“showstopper”。虽然你可以在这4列上创建唯一的组合键,但在你尝试插入另一个已经包含该组合的行之前,一切都没有问题。
举例来说:
此行失败,因为这样的组合已经存在(这是我插入的第一行)。
如果你同意的话--我的意思是,你真的希望这样的事情发生--那么它会起作用的。如果不是,就不会。
mu0hgdu02#
您可以通过创建唯一约束(而不是主键)来实现此目的。唯一约束允许它们的列成员可以为NULL,将NULL视为一个独特的值。这在可空列是某种状态/货币的指示符时特别有用(例如,NULL
end_date
可以表示历史类型2表中的当前活动行,并且该约束强制任何实体都不具有多于一个NULLend_date
,即多于一个活动/当前行)。如果你想创建一个约束,你会说:然而,你的特殊情况并不适合这样做。老实说,我无法想象为什么你会有一个设计,其中 shelf,order,customer 和 category 都是空的,也不能想象为什么你只在其中一个中有一个标识值,也不能想象为什么具有标识值的列会四处移动。除了 order 之外,所有这些听起来都不像是一个识别列,也不像是它们的组合。如果其中只有一个值,而其他值都没有,这是没有意义的。这是一个明确的设计缺陷,应该通过重新设计表来纠正。
要么纠正您的设计,使您有一个适当的标识键,或者干脆不尝试创建任何类型的键。表不必有约束。但我怀疑你可能应该修改设计,这样你就可以。