排除物料清单样式关系中的空值

发布于 2024-07-10 13:06:58 字数 358 浏览 5 评论 0原文

鉴于 PERSON.spouse 是 PERSON.name 的外键的模式

PERSON { name, spouse }

,当一个人未婚或我们没有任何信息时,NULL 将是必要的。

面对反对空值的争论,在这种情况下如何避免空值?

我有一个备用模式

PERSON { name }
SPOUSE { name1, name2 }

,其中 SPOUSE.name* 是 PERSON 的 FK。 我在这里看到的问题是,没有办法确保某人只有一个配偶(即使有所有可能的 UNIQUE 限制,也有可能有两个配偶)。

在物料清单样式关系中排除空值的最佳方法是什么?

Given the schema

PERSON { name, spouse }

where PERSON.spouse is a foreign key to PERSON.name, NULLs will be necessary when a person is unmarried or we don't have any info.

Going with the argument against nulls, how do you avoid them in this case?

I have an alternate schema

PERSON { name }
SPOUSE { name1, name2 }

where SPOUSE.name* are FKs to PERSON. The problem I see here is that there is no way to ensure someone has only one spouse (even with all possible UNIQUE constraints, it would be possible to have two spouses).

What's the best way to factor out nulls in bill-of-materials style relations?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

漆黑的白昼 2024-07-17 13:06:58

我认为,对这种类型的关系强制执行无 NULL 和无重复项会使模式定义比实际需要的更加复杂。 即使您允许空值,一个人仍然可能有多个配偶,或者有相互冲突的记录,例如:

PERSON { A, B }
PERSON { B, C }
PERSON { C, NULL }

您需要引入更多数据,例如性别(或同性的“配偶编号”)婚姻?)以确保,例如,只允许一种类型的人拥有配偶。 另一个人的配偶将根据第一个人的记录确定。 例如:

PERSON { A, FEMALE, B }
PERSON { B, MALE, NULL }
PERSON { C, FEMALE, NULL }

...因此只有女性才能拥有非空配偶。

但恕我直言,即使使用 NULL,这也过于复杂且不直观。 如果没有 NULL,情况会更糟。 我会避免进行这样的模式限制,除非您别无选择。

I think that enforcing no NULLs and no duplicates for this type of relationship makes the schema definition way more complicated than it really needs to be. Even if you allow nulls, it would still be possible for a person to have more than one spouse, or to have conflicting records e.g:

PERSON { A, B }
PERSON { B, C }
PERSON { C, NULL }

You'd need to introduce more data, like gender (or "spouse-numbers" for same-sex marriages?) to ensure that, for example, only Persons of one type are allowed to have a Spouse. The other Person's spouse would be determined by the first person's record. E.g.:

PERSON { A, FEMALE, B }
PERSON { B, MALE, NULL }
PERSON { C, FEMALE, NULL }

... So that only PERSONs who are FEMALE can have a non-null SPOUSE.

But IMHO, that's overcomplicated and non-intuitive even with NULLs. Without NULLs, it's even worse. I would avoid making schema restrictions like this unless you literally have no choice.

抚笙 2024-07-17 13:06:58

好吧,首先我会使用自动递增 ID,因为当然有人可能有相同的名字。 但是,我假设您打算这样做并且不会对此喋喋不休。 然而,反对 NULL 的争论到底是如何进行的呢? 我对 NULL 没有任何问题,并且认为这是解决这个问题的适当方法。

Well, first I would use auto-incrementing IDs as, of course, someone could have the same name. But, I assume you intend to do that and won't harp on it. However, how does the argument against NULLs go exactly? I don't have any problem with NULLs and think that is the appropriate solution to this problem.

如梦初醒的夏天 2024-07-17 13:06:58

我不确定为什么还没有人指出这一点,但实际上很容易确保一个人只有一个配偶,使用与您问题中几乎相同的模型。

我将暂时忽略使用名称作为主键(它可以更改并且重复很常见,因此这是一个糟糕的选择)并且我还将忽略历史跟踪的可能需要(你可能想添加某种生效日期,以便知道他们何时成为配偶 - Joe Celko 写了一些关于时间建模的好东西,但我不记得它目前在哪本书中)。 否则,如果我离婚并再婚,你就会失去我在另一个时间有另一个配偶的事实——也许这对你来说并不重要。

另外,您可能希望将姓名分解为名字、中间名、姓氏、前缀、后缀等。

考虑到这些注意事项...

CREATE TABLE People
(
     person_name     VARCHAR(100),
     CONSTRAINT PK_People PRIMARY KEY (person_name)
)
GO
CREATE TABLE Spouses
(
     person_name     VARCHAR(100),
     spouse_name     VARCHAR(100),
     CONSTRAINT PK_Spouses PRIMARY KEY (person_name),
     CONSTRAINT FK_Spouses_People FOREIGN KEY (person_name) REFERENCES People (person_name)
)
GO

如果您想让配偶也出现在“人员”表中,那么您可以为此添加一个外键,如下所示出色地。 然而,此时您正在处理双向链接,这会变得更加复杂。

I'm not sure why no one has pointed this out yet, but it's actually quite easy to ensure that a person has only one spouse, using pretty much the same model that you have in your question.

I'm going to ignore for the moment the use of a name as a primary key (it can change and duplicates are fairly common, so it's a poor choice) and I'm also going to leave out the possible need for historical tracking (you might want to add an effective date of some sort so that you know WHEN they were a spouse - Joe Celko has written some good stuff on temporal modeling, but I don't recall which book it was in at the moment). Otherwise if I got divorced and remarried you would lose that I had another spouse at another time - maybe that isn't important to you though.

Also, you might want to break up name into first_name, middle_name, last_name, prefix, suffix, etc.

Given those caveats...

CREATE TABLE People
(
     person_name     VARCHAR(100),
     CONSTRAINT PK_People PRIMARY KEY (person_name)
)
GO
CREATE TABLE Spouses
(
     person_name     VARCHAR(100),
     spouse_name     VARCHAR(100),
     CONSTRAINT PK_Spouses PRIMARY KEY (person_name),
     CONSTRAINT FK_Spouses_People FOREIGN KEY (person_name) REFERENCES People (person_name)
)
GO

If you wanted to have spouses appear in the People table as well then you could add an FK for that as well. However, at that point you're dealing with a bidirectional link, which becomes a bit more complex.

夜司空 2024-07-17 13:06:58

好吧,使用自动 ID,然后使用检查约束。 “Name1”列(仅是一个 int ID)将强制仅具有奇数编号的 ID,而 Name2 将仅具有偶数。

然后为 Column1 和 Column2 创建唯一约束。

All right, use Auto-IDs and then use a Check Constraint. The "Name1" column (which would only be an int ID) will be force to only have ODD numbered IDs and Name2 will only have EVEN.

Then create a Unique Constraint for Column1 and Column2.

戈亓 2024-07-17 13:06:58

好吧,首先使用名称以外的键,也许是 int 种子。 但为了防止某人拥有多个配偶,只需向配偶表中的parent(name1) 添加一个唯一索引即可。 这将阻止您两次插入相同的名称。

Well, begin with using a key other than name, perhaps a int seed. But to prevent someone from having more than one spouse, simply add a unique index to the parent(name1) in the spouse table. that will prevent you from ever inserting the same name1 twice.

玩物 2024-07-17 13:06:58

您需要一个人员表和一个单独的“Partner_Off”表来定义关系。

人(身份证、姓名等);

Partner_Off(id,partner_id,关系);

为了处理更复杂的社交情况,您可能需要一些日期,此外,为了简化 SQL,您需要一个条目(fred,wilma,husband)和一个匹配条目(wilma,fred,wife)。

You need a person TABLE and a separate "Partner_Off" table to define the relationship.

Person (id, name, etc );

Partner_Off (id, partner_id, relationship);

To deal with the more complex social situation you probaly would probably need some dates in there, plus, to simplify the sqls you need one entry for (fred,wilma,husband) and a matching entry for (wilma,fred,wife).

青柠芒果 2024-07-17 13:06:58

您可以使用触发器来强制执行约束。 PostgreSQL 有约束触发器,这是推迟约束评估的一种特别好的方法直到交易的适当时间。

来自 Fabian Pascal 的数据库管理中的实际问题,第 66-67 页:

存储过程——无论是触发还是
不——比应用更可取
级别完整性代码,但它们是
实际上不如且风险更大
而不是声明性支持,因为它们
写起来比较麻烦,报错
容易,并且无法从充分受益
DBMS 优化。

...

选择具有更好声明性的 DBMS
诚信支持。 鉴于
在这种支持方面存在相当大的差距
产品,知识渊博的用户将
至少能够效仿
正确——尽管有程序和/或应用程序代码的限制
DBMS 不支持。

You can use a trigger to enforce the constraint. PostgreSQL has constraint triggers, a particularly nice way to defer the constraint evaluation until the appropriate time in the transaction.

From Fabian Pascal's Practical Issues in Database Management, pp. 66-67:

Stored procedures—whether triggered or
not—are preferable to application
level integrity code, but they are
practically inferior to and riskier
than declarative support because they
are more burdensome to write, error
prone, and cannot benefit from full
DBMS optimization.

...

Choose DBMSs with better declarative
integrity support. Given the
considerable gaps in such support by
products, knowledgeable users would be
at least in a position to emulate
correctly—albeit with procedural and/or application code—constraints
not supported by the DBMS.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文