Substitute FROM ISNULL in where clause in ms sql server - sql

We used Stored Procedure on our Queries. Some of our field got NULL value, so for us to get this value we Put the conversion of ISNULL inside the WHERE condition but per checking it affects the Process of our strodproc based on the SQL performance tool.
Ex.
SELECT * FROM tblInfo
WHERE ISNULL(fldInfo,'') <> ''
tblInfo
fldinfo
NULL
30
NULL
20
Query
SELECT * FROM tblinfo WHERE fldinfo NOT IN (30,20) - different result
SELECT * FROM tblinfo WHERE ISNULL(fldinfo,'') NOT IN (30,20) - Correct
Result
Any other Substitute process of script we can use so that we can get the value but not affecting the performance of the query.

Your approach will be non sargable. Even though you have an index it will not be used.
Right way to do this would be using IS NOT NULL condition
SELECT * FROM tblInfo
WHERE fldInfo <> ''
AND fldInfo IS NOT NULL
If you don't have a index, then create a index on fldinfo to improve the performance
Update :
Not In fails to compare the NULL values. Comparison with NULL values are unknown so it is fails to return the NULL values. Here is the correct way to do this
SELECT *
FROM tblInfo
WHERE (fldinfo NOT IN ( 30, 20 ) OR fldinfo IS NULL)

COALESCE is one option that you can try. It behaves in the same way. However the differences between performance has to be evaluated by you with some test
Some differences between ISNULL and COALESCE are outlined here:
SQL - Difference between COALESCE and ISNULL?
EDIT: Based on the tests done by multiple people and by theory, ISNULL seems to be a better option over COALESCE
Which is quicker COALESCE OR ISNULL?

No need for IIF. Simply check for NULL
WHERE fldinfo IS NOT NULL
Or, of course, use IS NULL if you want rows where this condition is met

Related

Selecting rows which are not null in sql

Why doesn't the following code work in SQL
SELECT *
FROM DATA
WHERE VALUE != NULL;
we can not Compare null value with = We Special operator to compare null
value in sql
IS OPERATOR
SELECT *
FROM DATA
WHERE VALUE is not NULL;
Null is not any Value.Sql consider Null as Unknown/absence of data.
The condition you written is not in proper format.
If you want to select not null values from your table then you can use the following command
select *from table name where column name IS NOT NULL
If should work if you replace "!=" with "IS NOT".
Because a NULL value indicates an absence of data, it doesn't make sense to compare something with a value to it with an equals operator.
You can make your SELECT statement work by setting ANSI_NULLS OFF
SET ANSI_NULLS OFF
before running the statement. You can get further information here:
https://msdn.microsoft.com/en-us/library/ms188048.aspx
Null does not contain any value. Null is neither zero nor any value.
So we can't compare it using comparision operators.
Instead of using '=', you should use 'IS' keyword.
SELECT * FROM DATA WHERE VALUE IS NOT NULL;
The code will not work in SQL because it is not possible to test for NULL values with the following operators =, <, or <>. It is not possible to compare NULL and 0 as they are not equivalent.
You can test for NULL values using the IS NULL and IS NOT NULL operators instead.
SELECT *
FROM DATA
WHERE VALUE IS NOT NULL
http://www.w3schools.com/sql/sql_null_values.asp

What will be faster in UPDATE: COALESCE(field,value) or WHERE field is null

What query should be faster
UPDATE table1
SET field1 = COALESCE(field1, someValue)
WHERE foreignKeyField = someKeyValue
or
UPDATE table1
SET field1 = someValue
WHERE foreignKeyField = someKeyValue AND field1 is null
in MS SQL Server? What does it depend on?
ISNULL will have less overhead, depends on NULL conditions, i guess. Here is the test comparision of COALESCE vs. ISNULL vs. IS NULL OR -- http://blogs.x2line.com/al/archive/2004/03/01/189.aspx
Also, check out this blog for Performance comparion:ISNULL vs. COALESCE
http://sqlblog.com/blogs/adam_machanic/archive/2006/07/12/performance-isnull-vs-coalesce.aspx which says :
ISNULL appears to pretty consistently out-perform COALESCE by an
average of 10 or 12 percent.
Well, let me first state that your queries have 2 different meanings. Updating table1 and setting field1 equal to something always, even if it's NULL, is not equivalent to updating the table only where field1 is NULL. What are your intentions on your update?
Take this Fiddle for example:
SELECT Field FROM Test WHERE Field IS NULL;
SELECT COALESCE(Field,'') FROM Test;
The first query returns a single record and the second returns 2 records.
You may be wondering about the performance of:
SELECT COALESCE(Field,'') FROM Test;
SELECT ISNULL(Field,'') FROM Test;
Although I haven't tested it, ISNULL is suppose to be 20-30% more efficient.
Hope some of this helps. Good luck.

SQL Statement to set NULL Values to initialized values

In SQL or T-SQL how can I go through a table and set fields that are NULL to empty strings if the type is textual and 0 if the fields are integer types.
Thanks for any help, I do not even know where to begin.
Well if it's just one table use a basic update query:
UPDATE MyTable
SET NumericColumn = ISNULL(NumericColumn,0),
StringColumn= ISNULL(StringColumn,'')
What you're suggesting would only work as a "one off".
If you always want those fields to be populated going forward you can set a default value on the table.
You can use IsNull function in T-SQL,
Syntax :
ISNULL ( check_expression , replacement_value )
The function coalesce( expression_1 , expression_2 , ... ) is also useful in this context.
It evaluates the specified expressions from left to right and returns the value of the first expression that evaluates to a value other than null, or null if all the specified expressions evaluate to null.
This can be useful, especially in conjunction with left joins and table rotations.

Sql identical query but showing different Result

I have written a query in Sql server 2008.
select select * from program
where program_description <> null
But,Result of above query is blank.
whereas the below query is showing me the desired result.
select * from program
where program_description is not null
Is there any difference between them...?
Yes, = and <> do not work with null.
You have to use IS NULL or IS NOT NULL
Yes there is a difference. Comparing something with null will always result in unknown.
That is why you need to compare null results with is null
yes, the difference is -- according to standard, all operation with null return null. Including <>. The only valid way to check null value is operation 'is null'.

Invalid Number Error! Can't seem to get around it

Oracle 10g DB. I have a table called s_contact. This table has a field called person_uid. This person_uid field is a varchar2 but contains valid numbers for some rows and in-valid numbers for other rows. For instance, one row might have a person_uid of '2-lkjsdf' and another might be 1234567890.
I want to return just the rows with valid numbers in person_uid. The SQL I am trying is...
select person_uid
from s_contact
where decode(trim(translate(person_uid, '1234567890', ' ')), null, 'n', 'c') = 'n'
The translate replaces all numbers with spaces so that a trim will result in null if the field only contained numbers. Then I use a decode statement to set a little code to filter on. n=number, c=char.
This seems to work when I run just a preview, but I get an 'invalid number' error when I add a filter of...
and person_uid = 100
-- or
and to_number(person_uid) = 100
I just don't understand what is happening! It should be filtering out all the records that are invalid numbers and 100 is obviously a number...
Any ideas anyone? Greatly Appreciated!
Unfortunately, the various subquery approaches that have been proposed are not guaranteed to work. Oracle is allowed to push the predicate into the subquery and then evaluate the conditions in whatever order it deems appropriate. If it happens to evaluate the PERSON_UID condition before filtering out the non-numeric rows, you'll get an error. Jonathan Gennick has an excellent article Subquery Madness that discusses this issue in quite a bit of detail.
That leaves you with a few options
1) Rework the data model. It's generally not a good idea to store numbers in anything other than a NUMBER column. In addition to causing this sort of issue, it has a tendency to screw up the optimizer's cardinality estimates which leads to less than ideal query plans.
2) Change the condition to specify a string value rather than a number. If PERSON_UID is supposed to be a string, your filter condition could be PERSON_UID = '100'. That avoids the need to perform the implicit conversion.
3) Write a custom function that does the string to number conversion and ignores any errors and use that in your code, i.e.
CREATE OR REPLACE FUNCTION my_to_number( p_arg IN VARCHAR2 )
RETURN NUMBER
IS
BEGIN
RETURN to_number( p_arg );
EXCEPTION
WHEN others THEN
RETURN NULL;
END;
and then my_to_number(PERSION_UID) = 100
4) Use a subquery that prevents the predicate from being pushed. This can be done in a few different ways. I personally prefer throwing a ROWNUM into the subquery, i.e. building on OMG Ponies' solution
WITH valid_persons AS (
SELECT TO_NUMBER(c.person_uid) 'person_uid',
ROWNUM rn
FROM S_CONTACT c
WHERE REGEXP_LIKE(c.personuid, '[[:digit:]]'))
SELECT *
FROM valid_persons vp
WHERE vp.person_uid = 100
Oracle can't push the vp.person_uid = 100 predicate into the subquery here because doing so would change the results. You could also use hints to force the subquery to be materialized or to prevent predicate pushing.
Another alternative is to combine the predicates:
where case when translate(person_uid, '1234567890', ' ')) is null
then to_number(person_uid) end = 100
When you add those numbers to the WHERE clause it's still doing those checks. You can't guarantee the ordering within the WHERE clause. So, it still tries to compare 100 to '2-lkjsdf'.
Can you use '100'?
Another option is to apply a subselect
SELECT * FROM (
select person_uid
from s_contact
where decode(trim(translate(person_uid, '1234567890', ' ')), null, 'n', 'c') = 'n'
)
WHERE TO_NUMBER(PERSON_UID) = 100
Regular expressions to the rescue!
where regexp_like (person_uid, '^[0-9]+$')
Use the first part of your query to generate a temp table. Then query the temp table based on person_uid = 100 or whatever.
The problem is that oracle tries to convert each person_uid to an int as it gets to it due to the additional and statement in your where clause. This behavior may or may not show up in the preview depending on what records where picked.