何时在DB列中使用逗号分隔值?

Pro*_*irl 0 php mysql database database-design normalization

好的,我知道技术答案绝不是.

但是,有时候似乎通过更少的代码和看似很少的缺点使事情变得更容易,所以请在这里告诉我.

我需要构建一个名为" Restrictions跟踪"用户希望与之联系的用户类型的表,该表将包含以下3列(为简单起见):

minAge
lookingFor
drugs
Run Code Online (Sandbox Code Playgroud)

lookingFor并且drugs可以包含多个值.

数据库理论告诉我应该使用连接表来跟踪用户可能为这些列中的任何一列选择的多个值.

但似乎使用逗号分隔值使事情更容易实现和执行.这是一个例子:

假设用户1具有以下限制:

minAge => 18
lookingFor => 'Hang Out','Friendship'
drugs => 'Marijuana','Acid'
Run Code Online (Sandbox Code Playgroud)

现在让我们说用户2想要联系用户1.好吧,首先我们需要看看他是否符合用户1的限制,但这很容易,即使用逗号分隔的列,如下:

首先,我得到Target的(用户1)限制:

SELECT * FROM Restrictions WHERE UserID = 1
Run Code Online (Sandbox Code Playgroud)

现在我只是将它们放入PHP中的相应变量:

$targetMinAge = $row['minAge'];
$targetLookingFor = $row['lookingFor'];
$targetDrugs = $row['drugs'];
Run Code Online (Sandbox Code Playgroud)

现在我们只检查SENDER(用户2)是否符合这个简单的标准:

COUNT (*) 
   FROM Users
WHERE 
   Users.UserID = 2 AND
   Users.minAge >= $targetMinAge AND
   Users.lookingFor IN ($targetLookingFor) AND
   Users.drugs IN ($targetDrugs)
Run Code Online (Sandbox Code Playgroud)

最后,如果COUNT == 1,用户2可以联系用户1,否则他们不能.

如何简单的是THAT?它看起来真的很简单直接,所以只要我每次用户更新其联系限制时清理数据库的所有输入,这样做的真正问题是什么?能够使用MySQL的IN函数并且已经将它们理解的格式存储多个值(例如逗号分隔值)似乎比为每个多选列创建连接表要容易得多.我给出了一个简化的例子,但如果有10个多选列呢?然后事情开始变得混乱有这么多连接表,而CSV方法保持简单.

那么,在这种情况下,如果我使用逗号分隔值,它真的很糟糕吗?

********鸭

Lar*_*tig 7

你已经知道了答案.

首先,您的PHP代码甚至不能正常工作,因为它只有在用户2在LookingFor或Drugs中只有一个值时才有效.如果这些列中的任何一个包含多个以逗号分隔的值,那么即使这些值的顺序与用户1的值完全相同,IN也不会起作用.如果右侧有一个或多个逗号,IN会做什么?

因此,在PHP中执行您想要的操作并不"简单".它实际上非常痛苦,并且会将用户2的字段拆分为单个值,编写带有许多OR的动态SQL来进行比较,然后执行极低效的查询来获得结果.

此外,您甚至需要编写PHP代码来回答关于两组交集的这样一个相对简单的问题这一事实意味着您的设计存在严重缺陷.这正是 SQL存在要解决的问题(关系代数).正确的设计允许您解决数据库中的问题,然后在PHP或其他一些技术中简单地实现表示层.

做得对,你会有更轻松的时间.

  • 即使使用您给出的示例,情况也是如此,除非永远不允许用户1尝试联系任何人.该记录*已经*在两列中都有多个值 (2认同)
  • 如果您愿意将自己限制在您提出的单一要求中,您将能够以合理的方式解决您的问题(不再具有正确的方式,但您不会受到重创).但是,您将无法回答您最终想要查看的任何其他问题(例如,"为用户建议适当的联系人").做一个糟糕的设计决策,因为它会让你超过你的应用程序的0.1版本将花费你很多时间和金钱来修复以后. (2认同)