SQL nvl equivalent - without if/case statements & isnull & coalesce - sql

Are there any nvl() equivalent functions in SQL?
Or something close enough to be used in the same way in certain scenarios?
UPDATE:
no if statementsno case statementsno isnullno coalesce
select nvl (purge_date,"SODIUFOSDIUFSDOIFUDSF") from id_rec where id=36581;
(expression)
SODIUFOSDIUFSDOIFUDSF
1 row(s) retrieved.
select isnull (purge_date,"SODIUFOSDIUFSDOIFUDSF") from id_rec where id=36581;
674: Routine (isnull) can not be resolved.
Error in line 1
Near character position 8
select coalesce (purge_date,"SODIUFOSDIUFSDOIFUDSF") from id_rec where id=36581;
674: Routine (coalesce) can not be resolved.
Error in line 1
Near character position 8
select decode(purge_date, NULL, "01/01/2009", purge_date) from id_rec where id=74115;
800: Corresponding types must be compatible in CASE expression.
Error in line 1
Near character position 57

ISNULL (for a single replace)
or
COALESCE (Returns the first nonnull expression among its arguments.)

SQL Server:
IsNull or COALESCE
http://msdn.microsoft.com/en-us/library/ms184325.aspx
Sybase:
isnull function
http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.help.ase_15.0.blocks/html/blocks/blocks162.htm
Postgres:
I couldn't find one though haven't fully checked. Suggests to select where IS NULL and build from here
http://archives.postgresql.org/pgsql-sql/1998-06/msg00142.php
DB2 - COALESCE
http://publib.boulder.ibm.com/infocenter/db2luw/v8/index.jsp?topic=/com.ibm.db2.udb.doc/admin/r0000780.htm

You seem to be using Informix.
AFAIK, there is DECODE there:
DECODE(field, NULL, 'it is null, man', field) should give you same result as NVL(field, 'it is null, man')
Please post exact name and version of the RDBMS you are using.

The problem with your DECODE statement that is generating the 800 error is simple. '01/01/2009' is being treated as a string, and it's actually the 4th argument that generates the error.
Appreciate that the input and output of a DECODE statement can be different data-types, so the engine requires you to be more explicit in this case. (Do you want purge_date cast as a string or the string '01/01/2009', or the string argument parsed as a date or the original date? There's no way for the engine to know.
Try this:
SELECT DECODE(purge_date, NULL, '01/01/2009'::DATE, purge_date)
You could also write that 3rd argument as:
DATE('01/01/2009')
MDY(1,1,2009)
depending on version and personal preference.

Related

Division by NULL in IBM DB2

In Oracle, any number divided by NULL returns NULL. I was wondering what is the case for DB2 Databases?
The whole point of it is to check whether the following expression behaves in the same way for Oracle and DB2:
SELECT a / NULLIF(b, 0) FROM some_table;
Say b=0, we would get a division by null.
The NULLIF function returns the null value if the two arguments are equal; otherwise, it returns the value of the first argument.
-NULLIF(expression,expression)-------------------------------
The result of using NULLIF(e1,e2) is the same as using the CASE expression:
CASE WHEN e1=e2 THEN NULL ELSE e1 END
Copy
When e1=e2 evaluates to unknown because one or both arguments is null, CASE expressions consider the evaluation not true. In this case, NULLIF returns the value
of the first argument.
IBM DB2 docs
So for DB2 and oracle it works same way
Db2 returns null when one of the operators in a math expression is null. For example
values (3 / cast(null as integer)) will return null.
On the other hand, the definition of NULLID is equal to that in Oracle. If both arguments are equal, it will return null.

converted data type (varchar) still shows conversion error

I have a column that can store text but is used to store a number (I did not make the system!) someone has put a blank value in (i.e. not content but not null) and its causing error: -
Msg 8114, Level 16, State 5, Line 1
Error converting data type varchar to numeric.
I have reduced the issue down to the below: -
SELECT
T1.[FIELD_5],
ISNUMERIC(T1.[FIELD_5]),
NULLIF(T1.[FIELD_5],''),
ISNULL(NULLIF(T1.[FIELD_5],''),0),
CONVERT(DECIMAL(18,5),ISNULL(NULLIF(T1.[FIELD_5],''),0))
FROM
[MyTBL] T1
ORDER BY
ISNUMERIC(T1.[FIELD_5])
The issue data is in [FIELD_5]
I can see SQL sees a value as not numeric
I can see that NULLIF is successfully changing it to a NULL value
I can see the ISNULL is turning the NULLIF result to 0
But the CONVERT on the ISNULL result results in the error message, I would expect it to result in 0.00000
Use try_convert():
SELECT T1.[FIELD_5], ISNUMERIC(T1.[FIELD_5]), NULLIF(T1.[FIELD_5], ''),
COALESCE(NULLIF(T1.[FIELD_5], ''), 0),
TRY_CONVERT(DECIMAL(18, 5), COALESCE(NULLIF(T1.[FIELD_5], ''), 0))
FROM [MyTBL] T1
ORDER BY ISNUMERIC(T1.[FIELD_5]);
try_convert() was introduced in SQL Server 2012. If you are using an earlier version, then you need to use a case expression.
(I switched ISNULL() to COALESCE() because I prefer to use ANSI standard functions where practical.)
There is some non numeric value available you can do that check with case as below:
select convert(decimal(18,5), '')
Throws error as "Error converting data type varchar to numeric.
"
SELECT
T1.[FIELD_5],
ISNUMERIC(T1.[FIELD_5]),
NULLIF(T1.[FIELD_5],''),
ISNULL(NULLIF(T1.[FIELD_5],''),0),
CONVERT(DECIMAL(18,5), iif(isnumeric(ISNULL(T1.[FIELD_5]),'0') > 1,T1.[FIELD_5],'0')
ISNULL(NULLIF(T1.[FIELD_5],''),0))
FROM
[MyTBL] T1
ORDER BY
ISNUMERIC(T1.[FIELD_5])
This was a case of better investigation was needed, I should have realised as in my opinion SQL doesn't lie its normally always user error.
I run it again without the order by clause and then selected the row that would have shown up after the last row that did show up (i.e. that row that caused the error).
[FIELD_5] contained the value 1E-07, an infamous bad import from Excel!
What doesn't add up is why when I had the order by ISNUMERIC on, I did not see this value at the top of the list, only the blank values that were indeed being managed properly.
Question solved, I should have stuck investigating but I think this is worth leaving up to help other investigate in the future.

Oracle DECODE not working

I have an oracle decode that is checking if a value is NULL before updating the decimal precision. The problem is when the value in the price_precision column isn't null the decode still goes to the d.price value, but it should go to the default value. Here is the line of code for the decode:
DECODE(d.PRICE_PRECISION, NULL, d.price,TO_CHAR(DECODE(d.price,NULL, '', d.price), CONCAT('9999990',RPAD('D', d.PRICE_PRECISION+1,'9')))) price
I know for a fact there is non-NULL data in the Price _Precision column, because I can see it in the return for the select statement. Is there something wrong with my decode? any ideas why the decode isn't going to the default statement?
It seems implicit conversion took place. Consider this
DECODE(d.PRICE_PRECISION, NULL, to_char(d.price), TO_CHAR....
From Oracle docs:
Oracle automatically converts expr and each search value to the
datatype of the first search value before comparing. Oracle
automatically converts the return value to the same datatype as the
first result.
For Null values, use NVL function.
select nvl(name,'not registered') from table;
When name is null values, return 'not registered'.
You can use this together with DECODE function.
decode(nvl(PRICE,'Not valid'),'Not valid',0,PRICE)
In calculations, this avoids problems.
From Oracle docs:

SQL Server's ISNUMERIC function

I need to checking a column where numeric or not in SQL Server 2012.
This my case code.
CASE
WHEN ISNUMERIC(CUST_TELE) = 1
THEN CUST_TELE
ELSE NULL
END AS CUSTOMER_CONTACT_NO
But when the '78603D99' value is reached, it returns 1 which means SQL Server considered this string as numeric.
Why is that?
How to avoid this kind of issues?
Unfortunately, the ISNUMERIC() function in SQL Server has many quirks. It's not exactly buggy, but it rarely does what people expect it to when they first use it.
However, since you're using SQL Server 2012 you can use the TRY_PARSE() function which will do what you want.
This returns NULL:
SELECT TRY_PARSE('7860D399' AS int)
This returns 7860399
SELECT TRY_PARSE('7860399' AS int)
https://msdn.microsoft.com/en-us/library/hh213126.aspx
Obviously, this works for datatypes other than INT as well. You say you want to check that a value is numeric, but I think you mean INT.
Although try_convert() or try_parse() works for a built-in type, it might not do exactly what you want. For instance, it might allow decimal points, negative signs, and limit the length of digits.
Also, isnumeric() is going to recognize negative numbers, decimals, and exponential notation.
If you want to test a string only for digits, then you can use not like logic:
(CASE WHEN CUST_TELE NOT LIKE '%[^0-9]%'
THEN CUST_TELE
END) AS CUSTOMER_CONTACT_NO
This simply says that CUST_TELE contains no characters that are not digits.
Nothing substantive to add but a couple warnings.
1) ISNUMERIC() won't catch blanks but they will break numeric conversions.
2) If there is a single non-numeric character in the field and you use REPLACE to get rid of it you still need to handle the blank (usually with a CASE statement).
For instance if the field contains a single '-' character and you use this:
cast(REPLACE(myField, '-', '') as decimal(20,4)) myNumField
it will fail and you'll need to use something like this:
CASE WHEN myField IN ('','-') THEN NULL ELSE cast(REPLACE(myField, '-', '') as decimal(20,4)) END myNumField

Using Substring, within ISNULL in TSQL returns unexpected number of characters for the field

My field in my SKU table
(BI.dbo.SKU.phl5) is varchar(15)
However below code returns just 3 characters 'Unc' for the null fields in my table while it should return 'Uncategorized'. How to solve that?
ISNULL(SUBSTRING(BI.dbo.SKU.phl5,0,3),'Uncategorized') AS phl1
ISNULL(CAST(SUBSTRING(BI.dbo.SKU.phl5,0,3) AS VARCHAR(13)),'Uncategorized') AS phl1
The size of the return type of SUBSTRING isn't clearly documented that I can find, but the problem is that the type of ISNULL is the type of the first expression, which is clearly coming back as VARCHAR(3) since you are truncating it to 3 characters.
ISNULL docs
Try this
CASE WHEN BI.dbo.SKU.phl5 IS NULL THEN 'Uncategorized'
ELSE SUBSTRING(BI.dbo.SKU.phl5,0,3)
END AS phl1