如何构建一个表* *某些*列可以有多个值?

时间:2011-09-22 13:34:28

标签: php mysql database database-design

  

可能重复:
  How to Store Multiple Options selected by User in a Table

我对此非常困惑。

我希望我的用户能够限制可以联系他们的人。因此,我需要为每个用户及其选定的条件创建一个新的RESTRICTIONS表,该表将包含每个用户限制条件的列。这些专栏将包括年龄,收入,寻找,药物等。其中一些专栏(寻找,药物等)可能包含多个选择,其中存在我的问题。如何以这种方式构造表,考虑到某些条件(列)可以有多个值而其他条件没有?

我被告知有关连接表和枚举值(我之前从未使用过的这两个值),但我真的很困惑,我将如何构建一个表,其中一些列(不是全部),可以包含多个选择。

如何在表格的特定列中存储这些多个选项,以及如何构建RESTRICTIONS的整个表格?

5 个答案:

答案 0 :(得分:2)

DB列(至少在理论上)应该 NOT 保存多个值。不幸的是,有些程序员在一个列中存储多个值(例如用逗号分隔的值) - 那些程序员(在大多数情况下)破坏了DB和SQL的概念。

我建议您阅读 Database Normalization ,以便开始组织您的表格。并且,尽力实现 Codd's Third Normal Form

答案 1 :(得分:1)

您可能需要多个表格。

你已经拥有了“用户”表,对吗?如果您的某个“限制”条件每个用户只能有一个值,则该列属于“users”表。因此,您可能在users表中有“min_age”和“max_age”列,因为可能每个用户只有一个连续的年龄范围,他们正在寻找。

另一方面,对于可以具有多个值的每个限制条件,您需要一个新表。所以你可能有一个表“users_restrictions_drugs”,主键是(user,drug)。但是您可能还有一个表“users_restrictions_lookingfor”,其中主键是(user,lookingfor)。无论“寻找”是什么。

对于其中一些表,它可能有意义

  • 将第二列(非“用户”)列定义为枚举
  • 或(更好)有一个额外的表,用于列出第二列的可能值,并由外键引用。

答案 2 :(得分:1)

这是最简单的方法。多个属性成为第二个表中的行。

CREATE TABLE restrictions (
  user_id INTEGER PRIMARY KEY, -- references users (user_id), not shown
  age_restriction VARCHAR(10) NULL,
  income_restriction VARCHAR(20) NULL
);

CREATE TABLE looking_for (
  user_id INTEGER NOT NULL REFERENCES restrictions (user_id),
  looking_for VARCHAR(35) NOT NULL, -- could also be a foreign key.
  PRIMARY KEY (user_id, looking_for)
);

INSERT INTO restrictions (user_id) VALUES (1);
INSERT INTO restrictions (user_id, age_restriction) VALUES (2, '> 25');

INSERT INTO looking_for VALUES (1, 'boat');
INSERT INTO looking_for VALUES (1, 'dunky fazoo');

如果您想接受多个年龄限制,例如'> 25'和'< 55',你也可以为此建立另一张桌子。

要检索所有限制,请使用OUTER JOIN。

SELECT r.user_id, r.age_restriction, r.income_restriction, lf.looking_for
FROM restrictions r
LEFT JOIN looking_for lf ON lf.user_id = r.user_id

答案 3 :(得分:1)

table restrictions
user_id smoker_ok min_height max_height min_age max_age
-------------------------------------------------------
1       Y               150       200        24     34
2       N               100       180        32     57

table drug_restrictions
user_id     drug_id   drug_allowed
----------------------------------
1                H               N
1                M               Y
2                E               Y

将是一个例子。在限制表中,您可以存储显式的,奇异的值 - 吸烟者是或否,或最小和最大要求。 对于有多个选择的每个表,您可以创建一个连接表 - 我给出了一个药物示例。 在drug_restrictions表中,用户1表示她不希望人们使用H,但确实希望人们使用M.

此解决方案允许您使用“drug_id”作为数据库中任何表的外键,填充用户界面上的“药物”字段。它允许您对这些外键使用常规的标准SQL约定,并通过将它们声明为外键在数据库级别强制执行它们。

当然,缺点是你必须查询大量的表来查找匹配的记录,这并不是很有趣。

因此,您也可以遵循Catcall的建议 - 这会大大减少表的数量,但却无法使用“标准”外键完整性约束。这可能没问题 - 它肯定会更快。

我不愿意使用枚举 - 它们往往导致复杂的查询,而不是“标准”SQL。

答案 4 :(得分:0)

如果某些列具有重复值,则表没有问题。考虑用户的tbale;如果两个用户有相同的生日,那没问题吗?

唯一的问题是主键多次出现的表。例如,用户表可能会将username作为其主键,并且您不希望两个用户具有相同的用户名。

因此,制作一个列出用户的表,一个列出限制的表,以及一个连接两者的表。后者将为每个用户/权限组合提供一个条目。