How to use ISNULL in SQL between clause - sql-server

I have a SQL Server stored procedure that someone wrote where they are using isnull in the where clause in conjunction with the between keyword. They are using the following:
isnull(JobNumber, '') between #BeginJob and #EndJob
What will this comparison return if the JobNumber column is null? Thanks.

It will be translated as empty string, as ISNULL transforms the NULL values of param1 (column provided) into param2 value. So in your case you use the column values between x and y , but when null it will use ""
https://learn.microsoft.com/en-us/sql/t-sql/functions/isnull-transact-sql?view=sql-server-2017

This expression prevents the use of index on JobNumber, if such index exists. Remove isnull, the result will still be the same, but faster.

variable #BeginJob may be passed in any case with ''.Look like JobNumber column is null-able that's why in case of space get return all.
because no comparison in between two null values always get null.

Related

Passing Dynamic parameter using STRING_SPLIT to IN parameter

I am using SQL Server 2016 and I have to pass dynamic values to IN parameter.
For this reason, I am using a SPLIT_STRING() function that returns a table of items from a given comma-delimited string. It returns all the records if I passed the value like this (4,6,8) to the #Cylinders parameter.
Where CarCylinders IN (SELECT value FROM STRING_SPLIT(#Cylinders, ','))
But I have requirements where I want to pass Null value to the #Cylinder parameter. So that query returns all the records and ignores the condition.
I don't want to use dynamic SQL solution as the query is very complex and there are more than 20 input parameters.
Just use AND/OR logic:
where #Cylinders is null or CarCylinders IN (SELECT value FROM STRING_SPLIT(#Cylinders, ','))

How can I make LIKE match a number or empty string inside square brackets in T-SQL?

Is it possible to have a LIKE clause with one character number or an empty string?
I have a field in which I will write a LIKE clause (as a string). I will apply it later with an expression in the WHERE clause: ... LIKE tableX.FormatField .... It must contain a number (a single character or an empty string).
Something like [0-9 ]. Where the space bar inside square brackets means an empty string.
I have a table in which I have a configuration for parameters - TblParam with field DataFormat. I have to validate a value from another table, TblValue, with field ValueToCheck. The validation is made by a query. The part for the validation looks like:
... WHERE TblValue.ValueToCheck LIKE TblParam.DataFormat ...
For the configuration value, I need an expression for one numeric character or an empty string. Something like [0-9'']. Because of the automatic nature of the check, I need a single expression (without AND OR OR operators) which can fit the query (see the example above). The same check is valid for other types of the checks, so I have to fit my check engine.
I am almost sure that I can not use [0-9''], but is there another suitable solution?
Actually, I have difficulty to validate a version string: 1.0.1.2 or 1.0.2. It can contain 2-3 dots (.) and numbers.
I am pretty sure it is not possible, as '' is not even a character.
select ascii(''); returns null.
'' = ' '; is true
'' is null; is false
If you want exactly 0-9 '' (and not ' '), then you do to something like this (in a more efficient way than like):
where col in ('1','2','3','4','5','6','7','9','0') or (col = '' and DATALENGTH(col) = 0)
That's a tricky one... As far as I can tell, there isn't a way to do it with only one like clause. You need to do like '[0-9]' OR like ''.
You could accomplish this by having a second column in your TableX. That indicates either a second pattern, or whether or not to include blanks.
If I correctly understand your question, you need something that catches an empty string. Try to use the nullif() function:
create table t1 (a nvarchar(1))
insert t1(a) values('')
insert t1(a) values('1')
insert t1(a) values('2')
insert t1(a) values('a')
-- must select first three
select a from t1 where a like '[0-9]' or nullif(a,'') is null
It returns exactly three records: '', '1' and '2'.
A more convenient method with only one range clause is:
select a from t1 where isnull(nullif(a,''),0) like '[0-9]'

Using a CASE statement in ORDER BY clause with different data types

I want to use a CASE statement in my ORDER BY clause as follows:
DECLARE #SortOr TINYINT
SELECT #SortOr = 1
SELECT *
FROM [Table]
ORDER BY CASE WHEN #SortOr = 1 THEN col1
ELSE col2
END
But it throws an error:
Cannot convert varchar into tinyint.
What is the logic behind that? How can fix it?
The underlying issue that #Damien_The_Unbeliever states perfectly in the comments is:
A single CASE expression has to produce values of one data type. So if you have THENs that produce values of different data types, the system uses the precedence rules to decide which ones to convert.
You can replicate your CASE statement to work around this, where each CASE returns a single value/data type. This would be better than converting all values to VARCHAR as suggested in the other answer, which should also perform better (you will have to test):
So new ORDER BY clause will look like:
ORDER BY CASE WHEN #SortOr = 1 THEN col1
END ,
CASE WHEN #SortOr != 1 THEN col2
END -- If you need DESC it goes after END
Convert all returned values by the CASE statement to VARCHAR and it will work.
SQL Server tries to convert all your returned values implicitly, because they are part of the same expression and SQL Server wants them really to be the same type; it tries to convert to INT, because INT has higher precedence than VARCHAR; so you should set the same type for this explicitly.

SQL Server Nullable Column

I have a SQL Server table with a few columns of type varchar which are nullable. When an aspx page posts data if the textbox is empty, the database table column is updated to an empty string.
To maintain the null value rather han have it replaced by an empty string, I can either have the logic to change the empty string to System.DBnull in the middle tier c# code or do so in the stored procedure.
Are there other better ways to handle this situation?
you can use a trigger or do it in the proc, you can use the NULLIF function
Example
DECLARE #d VARCHAR(20)
SELECT #d = ''
SELECT NULLIF(#d,'')
I would probably put it near the code that makes a decision based on the distinction between an empty string and a null string. If there is no difference between their meaning or the resulting behavior of the application, I would suggest making the field non-nullable and sticking with an empty string.

MyNullableCol <> 'MyValue' Doesn't Includes Rows where MyNullableCol IS NULL

Today I found a strange problem that is I have a Table With a Nullable Column and I tried to use following Query
SELECT *
Id,
MyNCol,
FROM dbo.[MyTable]
WHERE MyNCol <> 'MyValue'
And Expecting it to return all rows not having 'MyValue' value in Field MyNCol. But its not returning all those Rows Containing NULL in above specified Column(MyNCol).
So I have to Rewrite my query to
SELECT *
Id,
MyNCol,
FROM dbo.[MyTable]
WHERE MyNCol <> 'MyValue' OR MyNCol IS NULL
Now My question is why is it why the first query is not sufficient to perform what i desire. :(
Regards
Mubashar
Look into the behaviour of "ANSI NULLs".
Standardly, NULL != NULL. You can change this behaviour by altering the ANSI NULLS enabled property on your database, but this has far ranging effects on column storage and query execution. Alternatively, you can use the SET ANSI_NULLS statement in your SQL script.
MSDN Documentation for SQL Server 2008 is here:
SET ANSI_NULLS (Transact-SQL)
Pay particular attention to the details of how comparisons are performed - even when setting ANSI_NULLS OFF, column to column comparisons may not behave as you intended. It is best practice to always use IS NULL and IS NOT NULL.
Equality operators cannot be performed on null values. In SQL 2000, you could check null = null, however in 2005 this changed.
NULL = UNKNOWN. So you can neither say that MyNCol = 'My Value' nor that MyNCol <> 'My Value' - both evaluate to UNKNOWN (just like 'foo' + MyNCol will still become NULL). An alternative to the workaround you posted is:
WHERE COALESCE(MyNCol, 'Not my Value') <> 'My Value';
This will include the NULL columns because the comparison becomes false rather than unknown. I don't like this option any better because it relies on some magic value in the comparison, even though that magic value will only be supplied when the column is NULL.

Resources