Add a value to a stored list in mySQL using FIND_IN_SET() and CONCAT()

For example, a column in a candy store database contains a list of flavors that the different shapes of candy come in. We have another table of flavors, but rather than a third relative table of flavors and product relationships, the IDs of the flavors are simply stored in a column in the products table.

So, you might have a value like 12,14,35,36,78,105 where each number represents the value of a form checkbox in the product admin for this site, and and ID for a flavor in the flavors table. The store admin checks the boxes for the flavors that product comes in, and those IDs get stored as a list in a specific column.

For the purpose of example, suppose the column is simply called 'flavors', and you need to add the flavor 'wowzaberry' (id 199) to all of the products that currently have the flavor 'razzoberry' (id 105) - with the added logic so that if a candy product already has the new flavor, we don't add it twice.


UPDATE tbl_products
SET flavors = CONCAT(flavors,',199')
WHERE FIND_IN_SET('105',flavors)
AND NOT FIND_IN_SET('199',flavors)

This says Add (concat) a comma (,) and 199 (the new ID number) To any record that already has ID 105 in the flavors column And that does not already have ID 199 in that same column

Comments (Comment Moderation is enabled. Your comment will not appear until approved.)
Very cool - I didn't know that there was a FIND_IN_SET() method in mySQL. There's so many random, but rather useful methods in mySQL. I know I've said this a number of times... but I really just need to read the documentation!
# Author Ben Nadel | 3/12/10 5:18 PM
@Ben:

>> There's so many random, but rather useful methods in mySQL

no kidding!
that's why i post these little snippets - if it can help somebody else, great, but really I'm just trying to put it where i can find it again!
# Author Michael Evangelista | 3/12/10 7:30 PM
Well it's much appreciated :)
# Author Ben Nadel | 3/12/10 7:35 PM
Thanks Michael, I wasn't aware of that one either. But I wonder why you would want to de-normalise your data by storing it as a list, rather than using a separate link table?

Also, I tend to be very wary of CONCAT(). For some reason I've never got round to researching, it will return NULL if any of its arguments are NULL. So if your "flavors" column contained NULL, your UPDATE statement wouldn't work for that row. CONCAT_WS() is usually best I find.
# Author Julian Halliwell | 3/15/10 4:13 AM
@Julian: i wouldn't want to denormalize but sometimes it just works out that way... just an example of something i've needed to do a gazillion times. Didn't know about concat_WS() - much more graceful than sticking the comma in there manually.

http://dev.mysql.com/doc/refman/4.1/en/string-func...

@Ben... YOU talkin' to ME?
Guess I need to stock up on miuaiga points, sorry, fresh out!
;-)
# Author Michael Evangelista | 3/15/10 12:26 PM
I *also* did not know about CONCAT_WS(). Very cool! Dangy, this is a good blog post :)
# Author Ben Nadel | 3/15/10 12:29 PM
As usual, there are several ways to do things. FIND_IN_SET was probably designed to assist in returning an index from a set for lookup, which would otherwise be rather messy to do. For that purpose it's rather neat, and thank you for bringing it up.

In this case, using LIKE and NOT LIKE in the where would have the same effect. Having come from DB2/Oracle/SQLserver, I tend toward more portable statements whenever possible (or practical).

Good comment on CONCAT and NULL, though I tend not to use NULLable fields unless there's a good reason, especially with multi-language DB access.
# Author Gerry Glauser | 6/9/10 6:14 PM
blogcfc 5.9.1.002 by raymond camden
contact michael evangelista