The Valdimir method is great for passing a flag variable to determine when a value is passed or failed, and its notes about randomly choosing a value are on the right track, but I would suggest that there are some arbitrary values that you will never worry about . for example -999 for an integer when you do not allow negative numbers, or '|||||||' for an empty string. Of course, this breaks some of them when you want to use negative numbers, but then you could play with numbers too large for a data type such as BIGINT, as the default parameter is -9223372036854775808 for int .... The problem really goes down to your business case about whether values may or may not be resolved.
However, if you go the route this way, I would suggest 2 things. 1) do not pass the value from PHP to SQL, but instead use the default value in SQL and check if the parameter is the default value. 2) Add CHECK CONSTRAINT to the table to make sure that the values are not used and cannot be represented in the table.
So something like:
ALTER TABLE dbo.UpdateTest CHECK CONSTRAINT chk_IsNotNullStandInValue (Field1 <> '|||||||||||||||||||' AND Field2 <> -999) CREATE PROCEDURE dbo.UpdateTest @ParamId numeric(10,0) ,@ParamField1 NVARCHAR(250) = '|||||||||||||||||||' ,@ParamField2 INT = -99999 --non negative INT ,@ParamField3 BIGINT = -9223372036854775808 --for an int that can be negative AS BEGIN DECLARE @ParamField3Value INT BEGIN TRY IF ISNULL(@ParamField3,0) <> -9223372036854775808 BEGIN SET @ParamField3Value = CAST(@ParamField3 AS INT) END END TRY BEGIN CATCH ;THROW 51000, '@ParamField3 is not in range', 1 END CATCH UPDATE dbo.Test SET Field1 = IIF(@ParamField1 = '|||||||||||||||||||',Field1,@ParamField1) ,Field2 = IIF(@ParamField2 = -99999,Field2,@ParamField2) ,Field3 = IIF(@ParamField3 = -9223372036854775808, Field3, @ParamField3Value) WHERE ID = @ParamId END
The real problem with this method is a numerical data field that allows negative numbers, since you really have no suitable way to determine when a value should be zero or not if you cannot choose a number that will always be from the assortment. And I definitely understand how bad the BIGINT idea is for the INT example, because now your procedure will accept a number range that it should not!
Another method / slight variation of Vladimir’s proposal is to indicate when to make the field null and not update. This will get a little used to what your PHP team will not want to use, but since these flags may also be optional, they should not be burdensome to always include something like:
CREATE PROCEDURE dbo.UpdateTest @ParamId numeric(10,0) ,@ParamField1 NVARCHAR(250) = NULL ,@MakeField1Null BIT = 0 ,@ParamField2 INT = NULL ,@MakeField2Null BIT = 0 ,@ParamField3 INT = NULL ,@MakeField3Null BIT = 0 AS BEGIN UPDATE dbo.Test SET Field1 = IIF(ISNULL(@MakeField1Null,0) = 1,NULL,ISNULL(@ParamField1,Field1)) ,Field2 = IIF(ISNULL(@MakeField2Null,0) = 1,NULL,ISNULL(@ParamField2,Field2)) ,Field3 = IIF(ISNULL(@MakeField3Null,0) = 1,NULL,ISNULL(@ParamField3,Field3)) WHERE ID = @ParamId END
Basically, if you use a stored procedure to update a table and it has fields with a zero value, I don’t think I would recommend that the parameters be optional, as this leads to business cases / situations that may be messy in the future , especially regarding numeric data types!