I have a database table, USER_OPTIONS, containing a field for each of a variety of options in an application, it looks effectively as follows:
USER_ID | OPTION_1 | OPTION_2 | OPTION_3 | ... | OPTION 20
----------------------------------------------------------
100 | true | true | false | ... | false
101 | true | true | false | ... | false
102 | false | false | false | ... | true
... etc etc
My application then wants to fire off an AJAX request to make adjustments to this table.
The information sent via AJAX is an array of database fields which have been changed, and their new values (in JSON format), e.g.
$my_new_settings === {
'OPTION_1' : 'false',
'OPTION_2' : 'false'
'OPTION_20' : 'true'
}
My plan was then to use a parameterised SQL query along the lines of
$query_string = "UPDATE `USER_OPTIONS`
SET ? = ?
WHERE
`USER_ID` = ?
LIMIT 1 ;";
$my_user_id = 100;
$my_field_for_updating = "OPTION_1";
$my_new_field_value = "false";
if ( $query = $mysqli->prepare($query_string) ) {
$query->bind_param("sss", $my_field_for_updating, $my_new_field_value, $my_user_id);
$query->execute();
$query->close();
}
And then iterate through the associative array to grab each other pair of $my_field_for_updating and $my_new_field_value from $my_new_settings.
However.
I have subsequently discovered the following in the php.net manual:
(“markers” are the term used for the “?” variables in the parameterised SQL query)
Note:
The markers are legal only in certain places in SQL statements. For
example, they are allowed in the VALUES() list of an INSERT statement
(to specify column values for a row), or in a comparison with a column
in a WHERE clause to specify a comparison value.However, they are not allowed for identifiers (such as table or column
names), in the select list that names the columns to be returned by a
SELECT statement, or to specify both operands of a binary operator
such as the = equal sign. The latter restriction is necessary because
it would be impossible to determine the parameter type. It’s not
allowed to compare marker with NULL by ? IS NULL too. In general,
parameters are legal only in Data Manipulation Language (DML)
statements, and not in Data Definition Language (DDL) statements.
Which has thus ruined my proposed solution.
My next idea was to have an SQL query that updated ALL the fields in the database, but to only include the newly updated field values. However I discovered that this would require a magic “do nothing” variable to assign to the “markers” for fields for which I have no data.
$query_string = "UPDATE `USER_OPTIONS`
SET `OPTION_1` = ?,
SET `OPTION_2` = ?,
SET `OPTION_3` = ?,
...
SET `OPTION_20` = ?
WHERE
`USER_ID` = ?
LIMIT 1 ;";
$my_user_id = 100;
$my_new_OPTION_1_value = 'false';
$my_new_OPTION_2_value = 'false';
$my_new_OPTION_20_value = 'true';
$magic_do_nothing_value = ????;
if ( $query = $mysqli->prepare($query_string) ) {
$query->bind_param("sssssssssssssssssssss",
$my_new_OPTION_1_value,
$my_new_OPTION_2_value,
$magic_do_nothing_value,
$magic_do_nothing_value,
...
$magic_do_nothing_value,
$my_new_OPTION_20_value,
$my_user_id
);
$query->execute();
$query->close();
}
However, I am unaware of what the $magic_do_nothing_value might actually be (and found it hard to google). Everything I tried either threw an error or was interpreted as ‘false’.
So my first question is: Is there a value which a MYSQL database accepts as a signal for “do nothing”?
Assuming there isn’t and moving on from this, my next thought was then to drag all the current values out of the database for the given USER_ID, amend these with the changes in $my_new_settings and then update the database accordingly with ALL the fields.
However this seems like a lot of unnecessary work, especially compared with my first solution.
Which leads me here to ask for a better one!
Thanks a lot for any thoughts you might have, I’m really interested to hear them. This is running on PHP 5.2 and a basic MySQL 5.0.92 database.
I would simply build the SQL dynamically and then bind the parameter values as you have done already. Here’s an example using a class to handle a dynamic number of parameters (class taken from PHP documentation). Please note I haven’t tested the code, but the logic should be clear anyway.