Snowflake: Insert null value in a numeric type column - sql

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

Related

Empty string being stored as null and need to differentiate between null and empty string in Orade [duplicate]

I am using Oracle DB. At the database level, when you set a column value to either NULL or '' (empty string), the fetched value is NULL in both cases. Is it possible to store '' (empty string) as a non NULL value in the database?
I execute this
UPDATE contacts SET last_name = '' WHERE id = '1001';
commit;
SELECT last_name, ID FROM contacts WHERE id ='1001';
LAST_NAME ID
------------ ------
null 1001
Is it possible to store the last_name as a non-NULL empty string ('')?
The only way to do this in oracle is with some kind of auxiliary flag field, that when set is supposed to represent the fact that the value should be an empty string.
As far as i know Oracle does not distinguish between '' and NULL, see here.
Oracle has a well know behavior that it silently converts "" to NULL on INSERT and UPDATE statements.
You have to deal with this in your code to prevent this behavior by converting NULL to "" when you read the columns back in and just do not use null in your program to begin with.
A long time since I used Oracle, but I believe we used to use a single space ' ' to represent an empty string, then trim it after reading.
If you use a VARCHAR2 data type then NULL and '' are identical and you cannot distinguish between them; so, as mentioned in other answers, you would either need to:
Have an additional column that contains a flag that distinguishes between non-NULL and NULL values so that if then flag states it is non-NULL and it contains a NULL then you know it is an empty string; or
Use an alternate representation, such as a single space character, for an empty string. This would then mean that you cannot store a string with that alternate representation; however, if trailing white-space was syntactically invalid for the strings you are storing then using a single space character to represent an empty string would be fine.
If you are using a CLOB data type then you CAN store an empty string using the EMPTY_CLOB() function:
CREATE TABLE table_name (value CLOB);
INSERT INTO table_name (value) VALUES (NULL);
INSERT INTO table_name (value) VALUES (EMPTY_CLOB());
INSERT INTO table_name (value) VALUES ('A');
Then:
SELECT value, LENGTH(value) FROM table_name;
Outputs:
VALUE
LENGTH(VALUE)
null
null
0
A
1
db<>fiddle here

Show 'Unknown' for Null Ids in SQL

when the numeric field is Null how to show a string value? Tried the syntax below but getting an error
'Error converting data type varchar to numeric':
Syntax:
select
case
when bill_area_id IS null then 'Unknown'
else bill_area_id end from Table_name
Use coalesce to return first non-null value :
select coalesce(bill_area_id, 'Unknown') from Table_name
Note that compatible data types is required. I.e. you may have to do :
select coalesce(cast(bill_area_id as varchar(15)), 'Unknown') from Table_name
If you are using sql server, you can also use this :
select isnull(cast(bill_area_id as varchar(15)), 'Unknown') from Table_name
The error is because you are mixing varchar with numeric output in the same column. For SQL Server for example:
select
case
when bill_area_id IS null then 'Unknown'
else CAST(bill_area_id as varchar) end from Table_name
Ensures that the output is uniformly varchar since I am casting bill_area_id as varchar, or selecting 'Unknown' (also a varchar).
There are other answers here using COALESCE/isnull that are just as valid, since those functions provide an alternative to NULL values.

Convert 'NULL' to Date in SQL

I have a column in my table called startdate. It is in string format. Most of the fields are 'NULL'. I am copying this column to another table which data type is 'Date'.
How can I convert all the values from string to Date in SQL.
I have tried this code:
INSERT INTO Destination_Table [new_date]
SELECT CONVERT(DATE,[startdate],103)
FROM Source_Table
nullif([startdate],'NULL') returns [startdate] unless it equals to 'NULL' and then it returns NULL (a real NULL, not the string 'NULL')
INSERT INTO Destination_Table [new_date]
SELECT CONVERT(DATE,nullif([startdate],'NULL'),103)
from Source_Table
For learning purposes, here are some expressions with the same results:
nullif(x,y)
case when x=y then null else x end
case x when y then null else x end
It looks like you are using MSSQL. If you are using MSSQL 2012, the following code should work :
INSERT INTO Destination_Table [new_date]
SELECT IIF([startdate] = "NULL", null, CONVERT(DATE,[startdate],103))
FROM Source_Table
What this does, is use the IIF() method to check the value of [startdate] and if the value is the text "NULL", then return the actual null value which can be allowed in most fields unless you have null disabled on the Destination_Table.[new_date] field.
Since the Date field can only accept and store Date/Time/Date&Time/(actual null) information, the text "NULL" is not valid.
Following is the equivalent for MySQL
INSERT INTO Destination_Table [new_date]
SELECT IF([startdate] == 'NULL', null, CONVERT(DATE,[startdate],103))
FROM Source_Table
(although I am unsure MySQL allows a conversion code as a param to CONVERT() )

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).

Is it possible to store '' (empty string) as a non NULL value in the database?

I am using Oracle DB. At the database level, when you set a column value to either NULL or '' (empty string), the fetched value is NULL in both cases. Is it possible to store '' (empty string) as a non NULL value in the database?
I execute this
UPDATE contacts SET last_name = '' WHERE id = '1001';
commit;
SELECT last_name, ID FROM contacts WHERE id ='1001';
LAST_NAME ID
------------ ------
null 1001
Is it possible to store the last_name as a non-NULL empty string ('')?
The only way to do this in oracle is with some kind of auxiliary flag field, that when set is supposed to represent the fact that the value should be an empty string.
As far as i know Oracle does not distinguish between '' and NULL, see here.
Oracle has a well know behavior that it silently converts "" to NULL on INSERT and UPDATE statements.
You have to deal with this in your code to prevent this behavior by converting NULL to "" when you read the columns back in and just do not use null in your program to begin with.
A long time since I used Oracle, but I believe we used to use a single space ' ' to represent an empty string, then trim it after reading.
If you use a VARCHAR2 data type then NULL and '' are identical and you cannot distinguish between them; so, as mentioned in other answers, you would either need to:
Have an additional column that contains a flag that distinguishes between non-NULL and NULL values so that if then flag states it is non-NULL and it contains a NULL then you know it is an empty string; or
Use an alternate representation, such as a single space character, for an empty string. This would then mean that you cannot store a string with that alternate representation; however, if trailing white-space was syntactically invalid for the strings you are storing then using a single space character to represent an empty string would be fine.
If you are using a CLOB data type then you CAN store an empty string using the EMPTY_CLOB() function:
CREATE TABLE table_name (value CLOB);
INSERT INTO table_name (value) VALUES (NULL);
INSERT INTO table_name (value) VALUES (EMPTY_CLOB());
INSERT INTO table_name (value) VALUES ('A');
Then:
SELECT value, LENGTH(value) FROM table_name;
Outputs:
VALUE
LENGTH(VALUE)
null
null
0
A
1
db<>fiddle here