在postgresql中模仿继承的最佳方法?

时间:2018-02-12 19:54:46

标签: orm

对于我正在撰写的应用程序,有两种类型的"用户",那些创建帐户的人和没有帐户的人virtual_users。这两种类型几乎相同,只有account_userspasswordemail是必需的,并且必须在所有account_users中都是唯一的,尽管它可以与任何数字相同为virtual_users。大量表格都有一个引用users的列,其中应包含两者,并且90%的应用功能将它们视为可互换。处理这个问题的最佳方法是什么?我考虑过的一些选择:

- 在同一个表中同时使用两种类型的用户,并且对于唯一性有一个复杂的约束,基本上,如果password不是NULL,email必须在所有users中{唯一} { {1}}不是NULL。我不知道怎么写这个约束。在少数情况下,我只想password仅查询account_users users的{​​{1}}。如果我能弄清楚如何编写约束,这似乎是最好的解决方案。

-Have password继承自Account_usersVirtual_users有一个额外的列Virtual_userspassword上的唯一约束。从这里有两个可能的选择:

---有一个email表,其中包含两列Usersaccount_user_id,其中一列为NULL,其中一列对应于相应的用户。当其他表需要引用virtual_user_id时,它们会引用此表。我的所有查询服务器端都让用户查询这两个表并进行组合。

---当其他表需要引用时,它们引用任一表。我不认为这是可能的。我的所有查询服务器端都让用户查询这两个表并进行组合。

任何建议都将受到赞赏。

1 个答案:

答案 0 :(得分:2)

我认为情况是你有一个系统,某些部分要求用户登录注册帐户,而其他部分则没有,但你仍然想跟踪用户。

Postgres has table inheritance。你可以使用它,但我会担心这些警告。

你可以把它们全部放到一个表中并使用某种标志,比如Single Table Inheritance,但是你会遇到约束问题。然后,您将在模型中强制执行约束。如果你有一个强大的模型,这应该没问题。

您可以单独accountsusers。而不是一个是另一个的特殊情况,他们关键是将它们视为两个概念上不同的东西。在OO术语中,帐户has a用户。

-- Visitors to the site who haven't signed up.
create table users (
    id          serial,

    -- The unverified email they might have given you.
    email       text,

    -- Any other common information like a tracking token
    token       text
);

-- Users who have registered.
create table accounts (
    id          serial,
    user_id     int references users(id),

    -- Their verified email.
    email       text not null,
    -- Hashed, of course.
    password    text not null

    -- any additional information only for accounts
);

我喜欢这个,因为没有涉及标志,usersaccounts可以有单独的约束,accounts表不会因为出现过一次的用户而变得臃肿回来了。

您可以通过简单的加入访问完整的帐户信息。

select accounts.*, users.token
from accounts
join users on accounts.user_id = users.id
where accounts.id = ?

如果要删除帐户,可以这样做而不会丢失基础用户信息。

delete from accounts where accounts.id = ?

需要帐户使用帐户的系统。不使用用户的系统。对用户和帐户行为不同的系统可以检查用户是否轻松拥有帐户。

select accounts.id
from accounts
where accounts.user_id = ?

用户跟踪与users表关联,因此您可以在用户注册之前和之后记录用户的行为。