tanger has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

I have a mysql db column name "checkboxes". I also have a HTML input checkbox named "checkboxes" with multiple values to be checked.

So my question is, whats the best way to store the checked values inside the column "checkboxes"

I'm new to using CGI.pm to handle form values. I do know that to retreive the checked values inside an array, I use this:
@checked_values = $cgi->param('checkboxes')
But now what? Do I do a foreach statement and append it to a string then store that string inside the mysql db?

I know that will work, but are there any better ways?
Thanks!

Replies are listed 'Best First'.
Re: Best way to store checkbox values into DB
by jhourcle (Prior) on Jun 29, 2005 at 12:08 UTC

    There is no one way that is best for every situation.

    You can store a deliminated string, but it's then harder to match against with SQL:

    my $field = join(',', @checked_values);

    But you then can't easily get the values out through SQL into a list -- or even search for items reliably. -- but if you only care about what the whole set is, rather than who selected item1, but not item3, this is just fine.

    Alternately, so that you can more easily do text-searching with SQL through the field, you can pad the beginning and end with a comma:

    my $field = join(',', '',@checked_values,'');

    So that you can then use SQL to get:

    SELECT * FROM tablename WHERE checkboxes LIKE '%,item1,%'

    Without worring about dealing with items that are first or last in the list, or the possibility that one item may be a sub-string of another item.

    But the full values of the checkboxes can take up a lot of space, so you can also key them, and assign a single letter to each value, and so, if you only had 10 items, you could number them 0 to 9, and just make the string from that. (you can easily get more than 60 values from lower alpha, upper alpha, and numbers) ... so we might store:

    my %keys = ( a => 'item1', b => 'item2', c => 'item3' ); my %encode = reverse @keys; my $field = join('', map { $encode{$_} } @checked_values);

    For space reduction, you can also use positional coding (eg, a string '011000' to represent that 2 of 6 choices were selected ... but this is a pain to search on, and causes problems if you add more options later), or you can use bitmasks (eg, from the same one above, we have items in position 3 and 4 (0 being the rightmost position), so 2**3 + 2**4 = 8 + 16 = 24, so we can store '24'. It's efficient storage for dealing with registers in a computer, but as a database, I find it to be annoying to deal with.

    Another option is to include single bit (boolean) columns for each option (is _very_ efficient storage in a database that can allocate fields that small, but it's best when the set of checkboxes is never going to change. It becomes less efficient when the set is exceptionally large, but the number selected is significantly small in relation to the size of the list.

    For these situations, we either use one of the earlier mentioned items, or we store your data in a normalized format -- you remove the 'checkboxes' field from your table, and make a 'checkboxes' table instead, which has a record for each checkbox-(whatever the original table was) pair. You'd store the (original table)'s primary key, and the value of the checkbox -- for size considerations, you might store the checkboxes' potential values in a seperate table, and just store a number that keys to the checkbox table's primary id.

    Which way is best? I have no idea. There are too many factors that you just haven't mentioned -- how often do we write new records? modify records? read the records? How do we read the records? (grab everything, selectively get records?) if selective, what are the selection criteria?

    If you think about these sorts of issues, it can help you lay out your data in a way that will be useful to you.

Re: Best way to store checkbox values into DB
by Cody Pendant (Prior) on Jun 29, 2005 at 10:20 UTC
    Do I do a foreach statement and append it to a string then store that string inside the mysql db?

    If I understand you correctly, no, you just need to do a join. Say $value_string = join(',',@checked_values), so you can get them out again and separate them with split() -- but the question arises, should you actually have created your DB in a different way, and had another table for these values altogether?



    ($_='kkvvttuu bbooppuuiiffss qqffssmm iibbddllffss')
    =~y~b-v~a-z~s; print
Re: Best way to store checkbox values into DB
by gube (Parson) on Jun 29, 2005 at 10:01 UTC
Re: Best way to store checkbox values into DB
by shiza (Hermit) on Jun 29, 2005 at 18:17 UTC
    As an addition to what was already suggested, I'd suggest this for your database design:

    You have a main table that stores your base information and a secondary table that stores the selected checkboxes.

    This might take a little longer to set up, but will save you some time and headache in the future.

    main table +------------------+ | Field | +------------------+ | id | | column_1 | +------------------+ secondary table +------------------+ | Field | +------------------+ | id | | main_table_id | | checkbox | +------------------+
    This, of course, is a basic example and there are other ways to accomplish what you are trying to do. The question guiding your decision should be:

    Do I anticipate this application to grow? If so, how much and how fast? Either way, it is always good practice to plan for growth.

    Also, if you're not using it already, take a look at Class::DBI.