I can easily write a stored procedure that would take inputs and use them to update a table:
CREATE PROCEDURE update_table (
IN parameter1 datatype1,
IN parameter2 datatype2,
...,
IN parameterN datatypeN
)
BEGIN
UPDATE
table_name
SET
column1 = parameter1,
column2 = parameter2,
...,
columnN = parameterN
WHERE
condition;
END;
This would work if I always wanted to update the same exact same predetermined set of columns every time the proc is called.
But, how could I create a proc that allowed me the flexibility to choose which columns to update? (I.e., update a different set of columns each time the proc is used, based on the parameters passed).
I thought about allowing the caller to set some parameters to NULL, and then only updating the columns that correspond to the non-NULL parameters, but that doesn’t work, because the caller would never be able to set a column to NULL if they wanted to.
I could also use some dynamic SQL, but that opens up the possibility of a SQL injection attack.
It seems like this is a common requirement that probably has a time-tested design pattern.
2
Answers
More detailed example from my comment, you can change it to update the columns every time but but only update values from parameters if they are not null:
(Updated to use Bill Karwin’s Suggestion from comments to use COALESCE instead of CASE NOT NULL check)
Not nearly as clean and can probably be tweaked to be better than what I have but the logic will work and still be better than dynamic SQL.
You could create a function or something to call for the case statement to make it more readable and easier to maintain.
Updated to give you the ability to set a value to NULL,
but you have to be able to do something on the app/code side to set the parameter value to something you would never pass to update the column to
I used: ‘@@@@@@@@@@’ string but this could be anything
This will update every column every time but if the parameter values are NULL then it will just update the column to the existing value in the column (thus not changing it), and if the parameter is not null, it will use that value to update the column.
As long as you dont have triggers on the columns this will work.
You can’t have unlimited flexibility at the same time as stability.
In Brad’s answer, the data value to set is overloaded as a control variable as well, determining whether to set the value or not.
If you must allow users to set any value including NULL, then you need to add more boolean columns to control which columns to set. This separates the logic from the data values to set.
Another approach would be to use JSON. I am reluctant to talk about this, because I see JSON so frequently abused in Stack Overflow questions. I don’t want to risk you thinking that JSON is a good way to store data.
JSON objects can have a NULL value for a given key, but also the key may be omitted from the JSON object. So this can be used to indicate which columns to set and which to leave as is.
But this requires your users to understand how to format the parameters argument in JSON.