NVL in Where clause doesn't return records which has null values - sql

I used this SELECT statement:
SELECT
ID
,SUB_TYPE
,SERVICE_ID
,MENU_TYPE
,MENU_DESCRIPTION
FROM MY_TABLE
WHERE SUB_TYPE = NVL('' , SUB_TYPE)
AND SERVICE_ID = NVL('' , SERVICE_ID)
AND MENU_TYPE = NVL('' , MENU_TYPE)
The rows that have null MENU_TYPE don't return , but I want these records to return
Thanks in advance

NULL is never equal to NULL. And in Oracle, '' is NULL.
Try this:
((:P_MENU_TYPE IS NULL AND MENU_TYPE IS NULL) OR MENU_TYPE = :P_MENU_TYPE)
(I put a bind variable :P_MENU_TYPE where you had '' because the SQL wouldn't make sense with ''!)
If what you really mean is, MENU_TYPE must match the parameter if the parameter is not null, and may be anything including null when the parameter is null then simply:
(:P_MENU_TYPE IS NULL OR MENU_TYPE = :P_MENU_TYPE)

Are you looking for rows in which all three columns are null? If so, you want:
WHERE SUB_TYPE is null
AND SERVICE_ID is null
AND MENU_TYPE in null

Related

Snowflake: Insert null value in a numeric type column

I have a case statement to rectify one business logic in snowflake:
INSERT INTO DB.table_b
SELECT
CASE
WHEN UPPER(emp) <> LOWER(emp) THEN NULL
WHEN emp IS NULL THEN nullif(emp, 'NULL')
ELSE emp
END AS emp_no
FROM
DB.table_a;
The 'table_a' content as below :
emp
-------
ABCD
NULL
''
23
It contains character string, null, empty and numbers. So, the requirement is to take only numbers and empty values from the case statement since the column emp_no in 'table_b' is numeric type. In source table if the column value is string then we have to insert NULL value. But as the 'table_b' column is of type 'numeric' the null value is not getting inserted and getting following error
Numeric value '' is not recognized
Using TRY_TO_NUMBER:
A special version of TO_DECIMAL , TO_NUMBER , TO_NUMERIC that performs the same operation (i.e. converts an input expression to a fixed-point number), but with error-handling support (i.e. if the conversion cannot be performed, it returns a NULL value instead of raising an error).
INSERT INTO DB.table_b
SELECT TRY_TO_NUMBER(emp) AS emp
FROM DB.table_a;
you can not use IS_INTEGER but for VARCHAR(16777216) it isn't supported
So a regular expression would be better
INSERT INTO DB.table_b
SELECT
CASE
WHEN regexp_like(emp,'^[0-9]+$') THEN emp
ELSE NULL
END AS emp_no
FROM
DB.table_a;
As Lukasz mentions you should use the TRY_TO_x functions (TRY_TO_NUMERIC, TRY_TO_DOUBLE) as these safely handle parsing the types, and return NULL if the parse fails. The extra note I will add is that both NUMBER/NUMERICs and DOUBLEs will parse 0.1234 but get different results, which you didn't mention as caring about, but I think is worth noting, so I am adding an extra answer to point the difference out.
The CTE is just to get the values into the SQL:
WITH data(emp) as (
select * from values
('ABCD'),
(NULL),
(''),
('0.123'),
('23')
)
SELECT emp
,try_to_numeric(emp) as emp_as_num
,try_to_double(emp) as emp_as_float
FROM data
EMP
EMP_AS_NUM
EMP_AS_FLOAT
'ABCD'
null
null
null
null
null
''
null
null
'0.123'
0
0.123
'23'
23
23
You can test for amp being string and set the string to NULL. Only numeric values will go into the second case statement.
SELECT
CASE
WHEN IS_VARCHAR(emp) then NULL else
case WHEN UPPER(emp) <> LOWER(emp) THEN NULL ELSE emp end
end AS emp_no

replace 'null' strings with NULL in sql

I wanted to check my column. If there was a 'null' string, I wanted to replace it with a NULL value. This works but is there a better way to do it? Such that I don't have to repeat the same thing twice JSON_DATA :"ContactPerson"::STRING
SELECT
IFF(JSON_DATA :"ContactPerson"::STRING = 'null',NULL, JSON_DATA :"ContactPerson"::STRING) AS "ContactPerson",
FROM TEST_TABLE
I want to use REPLACE or REGEX_REPLACE instead.
Using IS_NULL_VALUE could be a bit shorter:
SELECT
IFF(IS_NULL_VALUE(JSON_DATA:"ContactPerson"), NULL,
JSON_DATA :"ContactPerson"::STRING)
FROM TEST_TABLE;
or NULLIF:
Returns NULL if expr1 is equal to expr2, otherwise returns expr1.
SELECT NULIF(JSON_DATA :"ContactPerson"::STRING, 'null')
FROM TEST_TABLE;
Regarding comments:
Still, how would regex_replace be used? REGEXP_REPLACE( , [ , , , , ] )what would the subject be here?
REGEXP_REPLACE(JSON_DATA :"Business_Type"::STRING, 'null', NULL) AS "BS2",but this would give me NULL if "null" doesn't exist in the original value
CREATE FUNCTION:
CALLED ON NULL INPUT
Specifies the behavior of the UDF when called with null inputs. In contrast to system-defined functions, which always return null when any input is null, UDFs can handle null inputs, returning non-null values even when an input is null
and REPLACE function has this behaviour described explicitly"
If any of the arguments is a NULL, the result is also a NULL.

How to return a default value when a column value is null in SQL

How to return a default value when a column value is null in SQL
You can use COALESCE. Please refer https://www.sqlshack.com/using-the-sql-coalesce-function-in-sql-server/ for more info.
SELECT COALESCE (NULL,'A')
IsNull is used when the value is null and you want a default value to return.
Select IsNull(YourColumn, defaultvalue)
i.e.
Select IsNull( CandidateName , ''), -This is string column and return default value ''
IsNull(CandidateSalaryExpected, 0), --This is Integer/Double/Numeric column and return default value 0
IsNull(MaritalStatus , 0) --0 - marital means unmarried, 1 means married. This is boolean value
You can use Coalesce value too. Check the below link.
SQL Select Return Default Value If Null
Seems you are trying to fulfill your column with default value when any NULL value found.
You could try this:
SELECT COALESCE([dbo].YourTableName.[YourColumnName],'Default Value When Null Encountered') AS YourTableAlias FROM [dbo].[YourTable]
Test With Real Sample:
See my Table Column below where some FlatName is NULL
Real Query For Default Value When NULL Found:
SELECT FlatId,COALESCE([dbo].[Flat].[FlatName],'Default Value When Null Encountered') AS FlatName, FlatDescription FROM [dbo].[Flat]
Output Of Query:
Instead of returning default value, you can design your table to add default value if the value is not provided. See below example
CREATE TABLE DemoTable
(
ID INT,
Name VARCHAR(100),
RecordAddedOn DATETIME DEFAULT GETDATE()
)
You cane take a look at below link to have a better idea about default constraint. Default Constraint
However, if you want to return default value, you can use ISNULL(ColumnName, ‘Default Value’)

Oracle/PL SQL/SQL null comparison on where clause

Just a question about dealing will null values in a query.
For example I have the following table with the following fields and values
TABLEX
Column1
1
2
3
4
5
---------
Column2
null
A
B
C
null
I'm passing a variableY on a specific procedure. Inside the procedure is a cursor like this
CURSOR c_results IS
SELECT * FROM TABLEX where column2 = variableY
now the problem is variableY can be either null, A, B or C
if the variableY is null i want to select all record where column2 is null, else where column2 is either A, B or C.
I cannot do the above cursor/query because if variableY is null it won't work because the comparison should be
CURSOR c_results IS
SELECT * FROM TABLEX where column2 IS NULL
What cursor/query should I use that will accomodate either null or string variable.
Sorry if my question is a bit confusing. I'm not that good in explaining things. Thanks in advance.
Either produce different SQL depending on the contents of that parameter, or alter your SQL like this:
WHERE (column2 = variableY) OR (variableY IS NULL AND column2 IS NULL)
Oracle's Ask Tom says:
where decode( col1, col2, 1, 0 ) = 0 -- finds differences
or
where decode( col1, col2, 1, 0 ) = 1 -- finds sameness - even if both NULL
Safely Comparing NULL Columns as Equal
You could use something like:
SELECT * FROM TABLEX WHERE COALESCE(column2, '') = COALESCE(variableY, '')
(COALESCE takes the first non NULL value)
Note this will only work when you the column content cannot be '' (empty string). Else this statement will fail because NULL will match '' (empty string).
(edit)
You could also consider:
SELECT * FROM TABLEX WHERE COALESCE(column2, 'a string that never occurs') = COALESCE(variableY, 'a string that never occurs')
This will fix the '' fail hypothesis.
Below is similar to "top" answer but more concise:
WHERE ((column2 = variableY ) or COALESCE( column2, variableY) IS NULL)
May not be appropriate depending on the data you're looking at, but one trick I've seen (and used) is to compare NVL(fieldname,somenonexistentvalue).
For example, if AGE is an optional column, you could use:
if nvl(table1.AGE,-1) = nvl(table2.AGE,-1)
This relies on there being a value that you know will never be allowed. Age is a good example, salary, sequence numbers, and other numerics that can't be negative. Strings may be trickier of course - you may say that you'll never have anyone named 'xyzzymaryhadalittlelamb" or something like that, but the day you run with that assumption you KNOW they'll hire someone with that name!!
All that said: "where a = b or (a is null and b is null)" is the traditional way to solve it. Which is unfortunate, as even experienced programmers forget that part of it sometimes.
Try using the ISNULL() function. you can check if the variable is null and if so, set a default return value. camparing null to null is not really possible. remember: null <> null
WHERE variableY is null or column2 = variableY
for example:
create table t_abc (
id number(19) not null,
name varchar(20)
);
insert into t_abc(id, name) values (1, 'name');
insert into t_abc(id, name) values (2, null);
commit;
select * from t_abc where null is null or name = null;
--get all records
select * from t_abc where 'name' is null or name = 'name';
--get one record with name = 'name'
You could use DUMP:
SELECT *
FROM TABLEX
WHERE DUMP(column2) = DUMP(variableY);
DBFiddle Demo
Warning: This is not SARG-able expression so there will be no index usage.
With this approach you don't need to search for value that won't exists in your data (like NVL/COALESCE).

How do I incorporate "where [binary] is not null" in a T-SQL select statement?

I have a stored procedure that I need to filter rows that have a binary value and return only rows that are not null in the binary column.
When I execute this stored procedure:
create procedure sp_GetGraduatingStudentDataByYear
(
#year nvarchar(4)
)
as
select * from Cohort_Graduation_Student_Data where Exp_Grad_Year = #year and Off_Track != null
go
I get no results.
How can I alter this script to return the rows with a null value in the binary column?
This is not because it's a binary column, but because null in SQL should not be compared to anything. Essentially, Off_Track != null condition filters out all rows - all checks for column = null and column != null always evaluate to false.
Use is not null instead:
select *
from Cohort_Graduation_Student_Data
where Exp_Grad_Year = #year and Off_Track is not null