I have a SQL command that I've been asked to modify, and I'm having some troubles with the fact that what I'm passing to the SQL can now be null. If I'm passing a value, I can rely on the columnName = #parameterName in the SQL, but with NULL, I can't pass null or DBNull and have it correctly resolve.
Here's the SQL pseudocode:
SELECT
Columns
FROM
ClientSetup
WHERE
Client_Code = #ClientCode AND
Package_Code = #PackageCode AND
Report_Code = #ReportCode
The problem is that now #ReportCode can validly be NULL. In my C# code where I set up the SqlCommand, I can put in:
cmd.Parameters.Add("#ReportCode", SqlDBType.VarChar, 5).Value = reportType;
//reportType is a string, which can be null
But, if reportType is null, I need to use Report_Code IS NULL in the SQL, rather than Report_Code = #reportCode.
The solution I've found is to change the last where clause to the following:
((#ReportCode IS NULL AND Report_Code IS NULL) OR Report_Code = #ReportCode)
and the parameter phrase to
cmd.Parameters.Add("#ReportCode", SqlDBType.VarChar, 5).Value = string.IsNullOrEmpty(reportType) ? System.DBNull : reportType;
What this does works, but I was wondering if anyone knew of a cleaner or better way to handle nullable parameters when passing things to SQL from .NET code.
The short answer is that no, the SqlClient API requires you to pass in a DbNull.Value for NULL parameter values.
But I have some doubts about how you treat NULLs. For one you use string.IsNullOrEmpty which means that you treat the emtpy string as a NULL. This is questionable, there may be legitimate empty string values in the database.
My second concern is the logic of matching NULLs in the database. More often than not passing in a NULL parameter means that the request is interested in any value, not specifically in NULL values. I'm not saying your logic of matching NULL parameters to NULL values is flawed, I just want to make sure you know what you're doing.
Much of a muchness, in the past I've built the query
test reportcode for null if is its replace ReportCode = #ReportCode with "ReportCode is Null"
add the reportcode parameter if it isn't.
Generally though ReportCode of null signalled I wanted to select based on the other parameters and didn't care what the null one was.
It's a bit naughty
but Where IsNull(ReportCode,'') = IsNull(#ReportCode,'')
would give you what you want, given you are using IsNullOrEmpty.
Well, is correct the way how you fix it
only is (#ReportCode IS NULL AND Report_Code IS NULL) not is neccesary. because it is not c# o c++.
Some how that should be finally result
SELECT
Columns
FROM
ClientSetup
WHERE
Client_Code = #ClientCode
AND Package_Code = #PackageCode
AND (Report_Code = #ReportCode or #ReportCode is null)
Related
Suppose that I have:
case
when #ID ='2386002' then ISNULL(nullif(i.call,''),i.standingOrderNumber)
when nullif(rtrim(i.call),'') is null then
nullif(rtrim(i.standingOrderNumber), '')
else case when nullif(rtrim(i.standingOrderNumber),'') is null then rtrim(i.call)
else
rtrim(i.call)
This is just a part of the procedure which does synchronization between two apps, the problem is that standingOrderNumber is not synchronized and I assume it has to to do with this code portion.
Scenario:
After entering call and standingOrderNumber like this:
call: '' (leave it empty)
standingOrderNumber: 777777
Data is stored in a table and procedure takes the data from that table and displays it on the app form, problem is, everything is displayed correctly, except for this standingOrderNumber.
Can you tell if something went wrong in the logic I submitted above ?
I think problem with the below line,
when #ID ='2386002' then ISNULL(nullif(i.call,''),i.standingOrderNumber)
here you are trying to check i.call for null value and replacing it with empty string and that makes ISNULL function useless.
Solution is not to use nullif in above line
I have read all the related entries (here and at other sites) and have not found my situation.
I have a table (MyTable) with several date fields (MyDateField1, MyDateField2, etc) plus other fields not pertinent to this matter. All the date fields allow null values.
My application's tableadapter's insert method invokes the following stored procedure:
INSERT INTO MyTable VALUES (#MyDateField1Value, #MyDateField2Value,..., <other fields>);
using this VB code (dv is a dataview):
NewRow = dv.AddNew
NewRow(MyDate1Field) = DateValue1 <some date value taken off a window>
NewRow(MyDate2Field) = DateValue2 <some date value taken off a window>
....
NewRow.EndEdit()
MyTableTableAdapter.Insert(DateValue1, DateValue2, <etc>)
This works fine when none of the date fields is null. However, if I set:
NewRow(MyDate1Field) = DBNull.Value
I get the error message that DBNull.Value cannot be converted to a date value. How can I get a null value into MyDateField1, MyDateField2, etc.
The answer is to pass Nothing. Very simple - too bad it was so hard to find.
Excuse my language or SQL/Reporting wording
I am generating a report using Reporting Services where I have 2 drop down lists in order to show only by period and by category. I want it so if I select and I am shown all entries and if selected from any of the 2 drop downs then filter by those selections. I have a stored procedure which states the following on it's WHERE clause:
WHERE (dbo.PERIOD_LIST.PERIOD_DESC = #period) OR (dbo.CATEGORY.CATEGORY_DESC = #category)
However I cannot get this to work on Reporting Services/Visual Studio. I am shown ALL the entries instead of the filtered ones. I initialize #period and #category as NULL. So how can I make it so the report shows all rows when both attributes are null and still be able to filter by each or both of them?
How can I achieve this?
Edit: I used the suggestion Filip Popović gave me. If you're having this problem modify your prepared statement and make sure you refresh fields on your data sets since there's additional clauses on your prepared statement!
Note that in SQL, NULL = NULL is never evaluated to true. You can take it as NULL is not nothing it is something but unspecified. And You can't compare two unspecified values. You have to test COL1 IS NULL to get true if column has null value.
Try this:
WHERE ((dbo.PERIOD_LIST.PERIOD_DESC = #period) OR (#period IS NULL))
AND ((dbo.CATEGORY.CATEGORY_DESC = #category) OR (#category IS NULL))
Check the parameter for NULL as part of the condition:
WHERE ((#period IS NULL) OR (dbo.PERIOD_LIST.PERIOD_DESC = #period))
AND ((#category IS NULL) OR (dbo.CATEGORY.CATEGORY_DESC = #category))
I use jdbc to retrieve data from SQL Server, and ANSI_NULLS is off . So if I run
select * from cj_log where evt = null
I can get the result.
But when I put it in a statement like this
Statement st = DBConnection.getConnection().createStatement();
String sql = "select * from CJ_LOG where EVT=null";
ResultSet rs = st.executeQuery(sql);
The result set is empty. What is the problem here?
You need to say
where EVT is null
Nothing is ever equal to null, even null.
Think of it like this: Null means "don't know".
You are asking "is something I don't know equal to something I don't know"
The answer is "I don't know". So you don't get any rows.
I'm having some difficulty in understanding the following WHERE clause in a T-SQL (SQL Server 2000/2005) query:
update #tempTable
SET
Total_Avg=isnull(TerminationReason,'terminated'),
Individual_Subscriptions=null,
Business_Subscriptions=null,
Other_subscriptions=null,
-- snip. 10 more fields set to NULL.
PMIE_BI=null,
Digital_Editions_BI=null
where
(
AbcTerminationDate<=dbo.fnGetPeriodFinalDate(#periodid)
and (AbcTerminationDate!=19000101 or AbcTerminationDate is null)
and (Total_Avg is not NULL or PrevTotalAvg is not NULL)
)
Specifically, the second clause doesn't make sense to me - it's 2 sub-clauses separated by the OR operator seem contradictory.
The AbcTerminationDate field is declared as INT NULL in a table called Members. I believe a date of 19000101 in the system means NULL or a default value or no value, i.e. that a member is NOT terminated. So the query appears to blank out a whole lot of fields/figures if a member is marked as terminated, which would be when the AbcTerminationDate is NULL or has the default value.
Without knowing any more information, what do you make of it?
It does look like those are contradictory. Perhaps they meant
and !(AbcTerminationDate==19000101 or AbcTerminationDate is null)
?
Whatever 19000101 is "supposed" to mean, it is not the same as NULL in the eyes of the database. NULL is NULL. If you try to evaluate any other value to NULL then it can become problematic, because NULL means "unknown". For example, does 1=NULL? Maybe it does, maybe it doesn't. In fact, you can't even say that NULL=NULL, because each NULL is unknown so might or might not be equal to the other. It's safest to explicitly check for NULL conditions.
EDIT:
As I point out in my comment, if NULLs are to be included then the first part of the query precludes that. Here is how it should be written if NULLs should be included:
(
(
(
AbcTerminationDate <= dbo.fnGetPeriodFinalDate(#periodid) AND
AbcTerminationDate != 19000101
) OR
AbcTerminationDate is NULL
) AND
(Total_Avg is not NULL or PrevTotalAvg is not NULL)
)
If the "or" arg were outside the () grouping it would negate:
AbcTerminationDate<=dbo.fnGetPeriodFinalDate(#periodid)
[edit]
Basically it's saying to take whatever results are true from that 1st clause, and perform an additional filter to make sure it's not 19000101 or it's null, are most likely exceptional values for the fnGetPeriodFinalDate function to properly evaluate.