对于我正在撰写的应用程序,有两种类型的"用户",那些创建帐户的人和没有帐户的人virtual_users
。这两种类型几乎相同,只有account_users
有password
,email
是必需的,并且必须在所有account_users
中都是唯一的,尽管它可以与任何数字相同为virtual_users
。大量表格都有一个引用users
的列,其中应包含两者,并且90%的应用功能将它们视为可互换。处理这个问题的最佳方法是什么?我考虑过的一些选择:
- 在同一个表中同时使用两种类型的用户,并且对于唯一性有一个复杂的约束,基本上,如果password
不是NULL,email
必须在所有users
中{唯一} { {1}}不是NULL。我不知道怎么写这个约束。在少数情况下,我只想password
仅查询account_users
users
的{{1}}。如果我能弄清楚如何编写约束,这似乎是最好的解决方案。
-Have password
继承自Account_users
,Virtual_users
有一个额外的列Virtual_users
和password
上的唯一约束。从这里有两个可能的选择:
---有一个email
表,其中包含两列Users
和account_user_id
,其中一列为NULL,其中一列对应于相应的用户。当其他表需要引用virtual_user_id
时,它们会引用此表。我的所有查询服务器端都让用户查询这两个表并进行组合。
---当其他表需要引用时,它们引用任一表。我不认为这是可能的。我的所有查询服务器端都让用户查询这两个表并进行组合。
任何建议都将受到赞赏。
答案 0 :(得分:2)
我认为情况是你有一个系统,某些部分要求用户登录注册帐户,而其他部分则没有,但你仍然想跟踪用户。
Postgres has table inheritance。你可以使用它,但我会担心这些警告。
你可以把它们全部放到一个表中并使用某种标志,比如Single Table Inheritance,但是你会遇到约束问题。然后,您将在模型中强制执行约束。如果你有一个强大的模型,这应该没问题。
您可以单独accounts
和users
。而不是一个是另一个的特殊情况,他们关键是将它们视为两个概念上不同的东西。在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
);
我喜欢这个,因为没有涉及标志,users
和accounts
可以有单独的约束,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
表关联,因此您可以在用户注册之前和之后记录用户的行为。