Reputation: 5157
Code:
private void DoSomethingWithDatabase(string f1, int f2)
{
SqlCommand myCommand = new SqlCommand("SELECT Field1,Field2,Field3 FROM MyTable WHERE Field1 = @F1 AND Field2 = @F2", this.myConn);
myCommand.Parameters.Add("@F1", System.Data.SqlDbType.VarChar);
myCommand.Parameters.Add("@F2", System.Data.SqlDbType.Int);
if (f1 == "")
myCommand.Parameters["@F1"].Value = DBNull.Value;
else
myCommand.Parameters["@F1"].Value = f1;
if (f2 < 0)
myCommand.Parameters["@F2"].Value = DBNull.Value;
else
myCommand.Parameters["@F2"].Value = f2;
// code to do stuff with the results here
}
The server is a Microsoft SQL Server instance.
The database table MyTable
contains fields which are nullable. Therefore null is a valid value to search on when performing the query.
From my reading, and also from testing code like this, doing something like what I did here doesn't work properly because apparently you can't do an "equals null" comparison this way - you're supposed to do "IS NULL".
It looks like you can correct this and make it work by setting ANSI_NULL to OFF (as per https://msdn.microsoft.com/en-us/library/ms188048.aspx) but it also indicates this method is deprecated and should not be used.
That article suggests you can use an OR operator to do something like WHERE Field1 = 25 OR Field1 IS NULL
. The problem is, with a single call to this function, I want to check for either null and only null, or for the given constant value and nothing else.
So far, it seems like I need to basically build the query piece by piece, string by string, to account for the possibility of NULL values. So I'd need to do something like:
string theQuery = "SELECT Field1,Field2,Field3 FROM MyTable WHERE ";
if (f1 == "")
theQuery += "Field1 IS NULL ";
else
theQuery += "Field1 = @F1 ";
// ...
SqlCommand myCommand = new SqlCommand(theQuery, this.myConn);
if (f1 == "")
{
myCommand.Parameters.Add("@F1", System.Data.SqlDbType.VarChar);
myCommand.Parameters["@F1"].Value = f1;
}
// ...
Is this really how it needs to be done? Is there a more efficient way to do this without repeating that if
block and by using parameters rather than concatenating a query string together?
(Notes: An empty string is converted to a NULL here for the example. In the scenario I'm actually working with, empty strings are never used, but instead NULL is stored. The database is out of my control, so I can't just say "change all your NULLs to empty strings". Same goes for the ints - if we pass, say, -1
into the function it should be testing for a null value. Bad practice? Maybe, but the database itself is not in my control, only the code to access it is.)
Upvotes: 6
Views: 2703
Reputation: 23797
SqlCommand myCommand = new SqlCommand(@"SELECT Field1,Field2,Field3
FROM MyTable
WHERE
( (@F1 IS NULL AND [field1] IS NULL) OR [field1] = @F1 ) AND
( (@F2 IS NULL AND [field2] IS NULL) OR [field2] = @F2 );", this.myconn);
myCommand.Parameters.Add("@F1", System.Data.SqlDbType.VarChar).Value = DBNull.Value;
myCommand.Parameters.Add("@F2", System.Data.SqlDbType.Int).Value = DBNull.Value;
if (!string.IsNullOrEmpty(f1))
myCommand.Parameters["@F1"].Value = f1;
if (f2 != -1)
myCommand.Parameters["@F2"].Value = f2;
This would utilize indexes on fields.
Upvotes: 1
Reputation: 333
The way you are dealing with NULLs is the right way. Maybe you could use a helper method like this one:
private string AppendParameter(string query, string parameterName, string parameterValue, SqlParameterCollection parameters)
{
if (string.IsNullOrEmpty(parameterValue))
query += "Field1 IS NULL ";
else
{
query += "Field1 = " + parameterName + " ";
parameters.AddWithValue(parameterName, parameterValue);
}
return query;
}
Upvotes: 1
Reputation: 2136
Why not using:
string theQuery = "SELECT Field1, Field2, Field3 FROM MyTable WHERE ISNULL(Field1,'') = @F1";
?
That way you get rid of your if block and your null values are interpreted as an empty string, like your f1
variable.
Upvotes: 3
Reputation: 56697
You could do something like
WHERE ISNULL(Field, '') = @F1
In that case, NULL
fields are treated like empty strings. Another way would be:
WHERE Field IS NULL OR Field = @1
Upvotes: 1
Reputation: 1142
If you want to avoid if blocks, you can probably change the query into something like this:
SELECT Field1,Field2,Field3 FROM MyTable
WHERE COALESCE(Field1,'') = @F1 AND COALESCE(Field2,-1) = @F2
Upvotes: 0
Reputation: 613
SQL Server has a function called ISNULL(Column,Value)
where you can specify one column to check and set a Default Value in case this Column is NULL.
You can check here
Upvotes: 2