oracle 如何创建一个组合键,除了列之外的所有列都可以为空?

liwlm1x9  于 2023-10-16  发布在  Oracle
关注(0)|答案(2)|浏览(102)

我有一个没有自然主键的实体。唯一行由三列标识,其中任何一列都可以具有唯一值,其他列将为空。
为了一个假想的例子,这里是我的实体:

--------
Product
--------
Shelf
Order
Customer
Category
--------

只有货架或客户订单或类别列中的一个将具有填充值,可能具有ID(不会是另一个表中的FK)。
如何为它设计一张table?我只需要在这些列上标识唯一的行。我使用Oracle DB,如果它有帮助。

o4tp2gmn

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

此行失败,因为这样的组合已经存在(这是我插入的第一行)。
如果你同意的话--我的意思是,你真的希望这样的事情发生--那么它会起作用的。如果不是,就不会。

mu0hgdu0

mu0hgdu02#

您可以通过创建唯一约束(而不是主键)来实现此目的。唯一约束允许它们的列成员可以为NULL,将NULL视为一个独特的值。这在可空列是某种状态/货币的指示符时特别有用(例如,NULL end_date可以表示历史类型2表中的当前活动行,并且该约束强制任何实体都不具有多于一个NULL end_date,即多于一个活动/当前行)。如果你想创建一个约束,你会说:

constraint uq_product unique ("Shelf","Order","Customer","Category")

然而,你的特殊情况并不适合这样做。老实说,我无法想象为什么你会有一个设计,其中 shelfordercustomercategory 都是空的,也不能想象为什么你只在其中一个中有一个标识值,也不能想象为什么具有标识值的列会四处移动。除了 order 之外,所有这些听起来都不像是一个识别列,也不像是它们的组合。如果其中只有一个值,而其他值都没有,这是没有意义的。这是一个明确的设计缺陷,应该通过重新设计表来纠正。
要么纠正您的设计,使您有一个适当的标识键,或者干脆不尝试创建任何类型的键。表不必有约束。但我怀疑你可能应该修改设计,这样你就可以。

相关问题