开发者

When to use comma-separated values in a DB Column?

开发者 https://www.devze.com 2023-04-06 14:43 出处:网络
OK, I know the technical answer is NEVER. BUT, there are times when it seems to make things SO much easier with less code and seemingly few downsides, so please here me out.

OK, I know the technical answer is NEVER.

BUT, there are times when it seems to make things SO much easier with less code and seemingly few downsides, so please here me out.

I need to build a Table called Restrictions to keep track of what type of users people want to be contacted by and that will contain the following 3 columns (for the sake of simplicity):

minAge
lookingFor
drugs

lookingFor and drugs can contain multiple values.

Database theory tells me I should use a join table to keep track of the multiple values a user might have selected for either of those columns.

But it seems that using comma-separated values makes things so much easier to implement and execute. Here's an example:

Let's say User 1开发者_运维问答 has the following Restrictions:

minAge => 18
lookingFor => 'Hang Out','Friendship'
drugs => 'Marijuana','Acid'

Now let's say User 2 wants to contact User 1. Well, first we need to see if he fits User 1's Restrictions, but that's easy enough EVEN WITH the comma-separated columns, as such:

First I'd get the Target's (User 1) Restrictions:

SELECT * FROM Restrictions WHERE UserID = 1

Now I just put those into respective variables as-is into PHP:

$targetMinAge = $row['minAge'];
$targetLookingFor = $row['lookingFor'];
$targetDrugs = $row['drugs'];

Now we just check if the SENDER (User 2) fits that simple Criteria:

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

Finally, if COUNT == 1, User 2 can contact User 1, else they cannot.

How simple was THAT? It just seems really easy and straightforward, so what is the REAL problem with doing it this way as long as I sanitize all inputs to the DB every time a user updates their contact restrictions? Being able to use MySQL's IN function and already storing the multiple values in a format it will understand (e.g. comma-separated values) seems to make things so much easier than having to create join tables for every multiple-choice column. And I gave a simplified example, but what if there are 10 multiple choice columns? Then things start getting messy with so many join tables, whereas the CSV method stays simple.

So, in this case, is it really THAT bad if I use comma-separated values?

****ducks****


You already know the answer.

First off, your PHP code isn't even close to working because it only works if user 2 has only a single value in LookingFor or Drugs. If either of these columns contains multiple comma-separated values then IN won't work even if those values are in the exact same order as User 1's values. What do expect IN to do if the right-hand side has one or more commas?

Therefore, it's not "easy" to do what you want in PHP. It's actually quite a pain and would involve splitting user 2's fields into single values, writing dynamic SQL with many ORs to do the comparison, and then doing an extremely inefficient query to get the results.

Furthermore, the fact that you even need to write PHP code to answer such a relatively simple question about the intersection of two sets means that your design is badly flawed. This is exactly the kind of problem (relational algebra) that SQL exists to solve. A correct design allows you to solve the problem in the database and then simply implement a presentation layer on top in PHP or some other technology.

Do it correctly and you'll have a much easier time.


Suppose User 1 is looking for 'Hang Out','Friendship' and User 2 is looking for 'Friendship','Hang Out'

Your code would not match them up, because 'Friendship','Hang Out' is not in ('Hang Out','Friendship')

That's the real problem here.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号