如何创建除列之外的所有列都可为空的复合键?

问题描述 投票:0回答:2

我有一个没有任何自然主键的实体。唯一行由三列标识,其中任何一列都可以具有唯一值,其他列将为空。

为了一个虚构的例子,这是我的实体:

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

只有“货架”或“客户订单”或“类别”列之一具有填充值,可能带有 ID(不会是另一个表中的 FK)。

如何为其设计表格?我严格需要仅在这些列上识别唯一行。如果有帮助的话,我正在使用 Oracle DB。

sql database oracle database-administration
2个回答
0
投票

你很可能不能。

唯一的行由三列标识,其中任何一列都可以具有唯一值,其他列将为空

那是一个 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

此行失败,因为这样的组合已经存在(这是我插入的第一行)。

如果您同意 - 我的意思是,您确实希望发生这样的事情 - 那么它就会起作用。如果没有的话就不会了。


0
投票

您可以通过创建唯一约束(而不是主键)来做到这一点。唯一约束允许其列成员可以为 NULL,将 NULL 视为不同的值。当可空列是某种状态/货币指示符时(例如 NULL

end_date
可以表示历史类型 2 表中当前活动的行,并且约束强制没有实体具有多个 NULL),这尤其有用end_date,即多个活动/当前行)。如果你想创建一个约束,你会说:

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

但是,您的特殊情况不适合这样做。老实说,我无法想象为什么你会有一个设计,其中shelfordercustomercategory都可以为空。除了“顺序”之外,这些听起来都不像一个识别列,也不像它们的组合。仅其中一项有价值而其他则没有价值是没有意义的。 要么纠正您的设计,以便拥有正确的识别密钥,要么干脆不要尝试创建任何类型的密钥。表不必有约束。但我怀疑你可能应该修改设计,这样你就可以了。

© www.soinside.com 2019 - 2024. All rights reserved.