I am trying to replace null values with a blank space but its throwing an error in snowflake.
select
case when CALL_DATE IS NULL then ' ' ELSE CALL_DATE end as CALL_DATE_NEW
from Table_x
The problem is the derived column CALL_DATE_NEW gets implicitly cast to type timestamp. As the error indicates, you can't specify a space as a timestamp. You can; however, specify a timestamp as a varchar:
create or replace temp table X (CALL_DATE timestamp);
insert into X values ('2021-12-03'), (null);
select case when CALL_DATE IS NULL then ' ' ELSE CALL_DATE end as CALL_DATE_NEW from x; -- Timestamp '' is not recognized
select case when CALL_DATE IS NULL then ' ' ELSE to_varchar(CALL_DATE) end as CALL_DATE_NEW from x; -- Works by keeping the types consistent
Date data types can be null or contain data and/or time data.
They cannot contain Space. Sorry.
Related
I have a column which has varchars like "172.54". I am trying to insert into another table where this columns datatype is float. I am getting error saying can not convert datatype varchar to float. So I do
SELECT *
FROM TBL
WHERE ISNUMERIC(COLNAME) <> 1
And I get no results. But casting is not working. So I look and I have empty strings in that column. So I try to
SELECT *
FROM TBL
WHERE COLNAME = ''
And also every other different amount of spaces.
I ultimately just want to convert the empty strings to null
Also len(colname) = 1
declare #test varchar(10) = ' ' -- any number of spaces is equivalent to ''
select try_convert( float, #test ) as floatval -- '' gives you 0
select case when #test = '' then NULL else try_convert( float, #test ) end as floatval -- value '' returns NULL instead of 0
I guess you column has some characters other than numeric data. Also empty string will be converted to zero it will not throw error.
To filter Numeric data use
COLNAME not like '%[^0-9]%'
Try something like this
insert into tablename (col1,col2)
SELECT col1,col2 FROM TBL
COLNAME not like '%[^0-9]%'
I wrote a T-SQL Statement similar like this (the original one looks different but I want to give an easy example here):
SELECT first_name +
CASE last_name WHEN null THEN 'Max' ELSE 'Peter' END AS Name
FROM dbo.person
This Statement does not have any syntax errors but the case-clause always chooses the ELSE-part - also if the last_name is null. But Why?
What I want to do is to unite first_name and last_name, but if last_name is null the whole name becomes null:
SELECT first_name +
CASE last_name WHEN null THEN '' ELSE ' ' + last_name END AS Name
FROM dbo.person
Do you know where the problem is?
CASE WHEN last_name IS NULL THEN '' ELSE ' '+last_name END
The WHEN part is compared with ==, but you can't really compare with NULL. Try
CASE WHEN last_name is NULL THEN ... ELSE .. END
instead or COALESCE:
COALESCE(' '+last_name,'')
(' '+last_name is NULL when last_name is NULL, so it should return '' in that case)
There are plenty of solutions but none covers why the original statement doesn't work.
CASE last_name WHEN null THEN '' ELSE ' '+last_name
After the when, there is a check for equality, which should be true or false.
If one or both parts of a comparison is null, the result of the comparison will be UNKNOWN, which is treated like false in a case structure. See: https://www.xaprb.com/blog/2006/05/18/why-null-never-compares-false-to-anything-in-sql/
To avoid this, Coalesce is the best way.
Given your query you can also do this:
SELECT first_name + ' ' + ISNULL(last_name, '') AS Name FROM dbo.person
The problem is that null is not considered equal to itself, hence the clause never matches.
You need to check for null explicitly:
SELECT CASE WHEN last_name is NULL THEN first_name ELSE first_name + ' ' + last_name
try:
SELECT first_name + ISNULL(' '+last_name, '') AS Name FROM dbo.person
This adds the space to the last name, if it is null, the entire space+last name goes to NULL and you only get a first name, otherwise you get a firts+space+last name.
this will work as long as the default setting for concatenation with null strings is set:
SET CONCAT_NULL_YIELDS_NULL ON
this shouldn't be a concern since the OFF mode is going away in future versions of SQl Server
The issue is that NULL is not considered to be equal to anything even not to itself, but the strange part is that is also not not equal to itself.
Consider the following statements (which is BTW illegal in SQL Server T-SQL but is valid in My-SQL, however this is what ANSI defines for null, and can be verified even in SQL Server by using case statements etc.)
SELECT NULL = NULL -- Results in NULL
SELECT NULL <> NULL -- Results in NULL
So there is no true/false answer to the question, instead the answer is also null.
This has many implications, for example in
CASE statements, in which any null value will always use the ELSE clause unless you use explicitly the WHEN IS NULL condition (NOT the WHEN NULL condition )
String concatenation, as
SELECT a + NULL -- Results in NULL
In a WHERE IN or WHERE NOT IN clause, as if you want correct results make sure in the correlated sub-query to filter out any null values.
One can override this behavior in SQL Server by specifying SET ANSI_NULLS OFF, however this is NOT recommended and should not be done as it can cause many issues, simply because deviation of the standard.
(As a side note, in My-SQL there is an option to use a special operator <=> for null comparison.)
In comparison, in general programming languages null is treated is a regular value and is equal to itself, however the is the NAN value which is also not equal to itself, but at least it returns 'false' when comparing it to itself, (and when checking for not equals different programming languages have different implementations).
Note however that in the Basic languages (i.e. VB etc.) there is no 'null' keyword and instead one uses the 'Nothing' keyword, which cannot be used in direct comparison and instead one needs to use 'IS' as in SQL, however it is in fact equal to itself (when using indirect comparisons).
Found a solution to this. Just ISNULL the CASE statement:
ISNULL(CASE x WHEN x THEN x ELSE x END, '') AS 'BLAH'
CASE
WHEN last_name IS null THEN ''
ELSE ' ' + last_name
END
Jason caught an error, so this works...
Can anyone confirm the other platform versions?
SQL Server:
SELECT
CASE LEN(ISNULL(last_name,''))
WHEN 0 THEN ''
ELSE ' ' + last_name
END AS newlastName
MySQL:
SELECT
CASE LENGTH(IFNULL(last_name,''))
WHEN 0 THEN ''
ELSE ' ' + last_name
END AS newlastName
Oracle:
SELECT
CASE LENGTH(NVL(last_name,''))
WHEN 0 THEN ''
ELSE ' ' + last_name
END AS newlastName
When you get frustrated trying this:
CASE WHEN last_name IS NULL THEN '' ELSE ' '+last_name END
Try this one instead:
CASE LEN(ISNULL(last_Name,''))
WHEN 0 THEN ''
ELSE ' ' + last_name
END AS newlastName
LEN(ISNULL(last_Name,'')) measures the number of characters in that column, which will be zero whether it's empty, or NULL, therefore WHEN 0 THEN will evaluate to true and return the '' as expected.
I hope this is a helpful alternative.
I have included this test case for sql server 2008 and above:
DECLARE #last_Name varchar(50) = NULL
SELECT
CASE LEN(ISNULL(#last_Name,''))
WHEN 0 THEN ''
ELSE 'A ' + #last_name
END AS newlastName
SET #last_Name = 'LastName'
SELECT
CASE LEN(ISNULL(#last_Name,''))
WHEN 0 THEN ''
ELSE 'A ' + #last_name
END AS newlastName
I tried casting to a string and testing for a zero-length string and it worked.
CASE
WHEN LEN(CAST(field_value AS VARCHAR(MAX))) = 0 THEN
DO THIS
END AS field
You can use IsNull function
select
isnull(rtrim(ltrim([FirstName]))+' ','') +
isnull(rtrim(ltrim([SecondName]))+' ','') +
isnull(rtrim(ltrim([Surname]))+' ','') +
isnull(rtrim(ltrim([SecondSurname])),'')
from TableDat
if one column is null you would get an empty char
Compatible with Microsoft SQL Server 2008+
Use the CONCAT function available in SQL Server 2012 onward.
SELECT CONCAT([FirstName], ' , ' , [LastName]) FROM YOURTABLE
NULL does not equal anything. The case statement is basically saying when the value = NULL .. it will never hit.
There are also several system stored procedures that are written incorrectly with your syntax. See sp_addpullsubscription_agent and sp_who2.
Wish I knew how to notify Microsoft of those mistakes as I'm not able to change the system stored procs.
In SQL Server 2017, Microsoft introduced a Concatenate With Separator function, for just your situation:
SELECT CONCAT_WS(' ', first_name, last_name) FROM dbo.person
CONCAT_WS skips NULL values, but not empty strings.
Interestingly, MySQL introduced CONCAT_WS over a decade earlier.
You can use like this:
CASE IsNull(last_name,'') WHEN '' THEN 'Max' ELSE 'Peter' END AS Name
I have a database in SQL Server. I do not have authorization to change any table but I can create views.
I have three varchar columns which store dates in the format YYYYMMDD. I want to create a view where the dates are converted from varchar to datetime.
Now it can be the case that instead of a date in this columns I can have empty space, NULL or the character -.
Let's take the closedDate column. If I use CONVERT(datetime, closedDate, 112)
Valid dates are converted correctly,
When there is empty space the date is converted to 1900-01-01,
NULL is kept,
The - causes a conversion error:
The conversion of a varchar data type to a datetime data type resulted
in an out-of-range value.
How can I tell to the function to convert dates just if it has valid date form and leave NULL or better an empty date(or space) in all the other cases?
Try this
CASE WHEN ISDATE(closedDate) = 1 THEN CONVERT(datetime, closedDate, 112)
ELSE NULL END closedDate
Use below code
SELECT CASE WHEN ISDATE(datecolumn)=1 THEN CONVERT(datetime, datecolumn, 103 )
ELSE null END
FROM tablename
use below for empty data
SELECT CASE WHEN ISDATE(datecolumn)=1 THEN CONVERT(datetime, datecolumn, 103 )
ELSE '' END
FROM tablename
I'm having an issue with the below query:
SELECT
Consignments.LegacyID,
Consignments.TripDate,
Consignments.CollectionName,
CASE
WHEN Sage2.InvoiceSummaryType = 'HT' THEN DeliveryTown
ELSE DeliveryName + ', ' + DeliveryTown + ', ' + DeliveryPostCode END AS 'DeliveryName',
Consignments.Pallets,
Consignments.Weight,
Consignments.BaseRate,
Consignments.FuelSurcharge,
Consignments.AdditionalCharges,
Consignments.BaseRate * Consignments.Quantity AS 'InvoiceValue',
Consignments.InvoiceNumber,
Consignments.Customer
FROM
Consignments
INNER JOIN SageAccount
ON Consignments.Customer = SageAccount.LegacyID
AND SageAccount.Customer = 'true'
LEFT OUTER JOIN SageAccount AS Sage2
ON SageAccount.InvoiceAccount = Sage2.LegacyID
WHERE
(Sage2.Customer = 'true')
AND (Consignments.Customer = #Customer)
AND (Consignments.InvoiceNumber IS NOT NULL)
OR (Sage2.Customer = 'true')
AND (Consignments.InvoiceNumber IS NOT NULL)
AND (Sage2.InvoiceAccount = #Customer)
ORDER BY
CASE
WHEN Sage2.InvoiceSummaryType = 'HR' THEN TripDate
WHEN Sage2.InvoiceSummaryType = 'HS' THEN Consignments.LegacyID
END
For some reason, it keeps giving me the following error:
The conversion of a char data type to a datetime data type resulted in an out-of-range datetime value order by
But only when it tries to Order By TripDate, i.e. when the case 'HR' happens. TripDate is a 'datetime field'.
Any ideas?
Having just read the question again I can't explain the specific symptons you are getting without seeing the execution plan (I would have expected HS to cause the problem). Generally though you should avoid mixing datatypes in CASE expressions as below as it simply doesn't work select case when 1=0 then GETDATE() else 'foo' end will fail as it tries to convert the string to datetime
ORDER BY
CASE
WHEN Sage2.InvoiceSummaryType = 'HR'
THEN TripDate
WHEN Sage2.InvoiceSummaryType = 'HS'
THEN Consignments.LegacyID
END
To get around this you can use cast(TripDate as float) - assuming (perhaps incorrectly) that the ID field is numeric or use this idiom.
ORDER BY
CASE
WHEN Sage2.InvoiceSummaryType = 'HR'
THEN TripDate
ELSE NULL
END,
CASE
WHEN Sage2.InvoiceSummaryType = 'HS'
THEN Consignments.LegacyID
ELSE NULL
END
You would need to check the execution plans for performance comparisons.
Don't you need an "END" after your THEN TripDate ?
All the options in the CASE statement have to be the same datatype. Is LegacyID a char?
You'd have this problem anywhere, not just in an order by. If you do CASE WHEN 'x' THEN (some int) WHEN 'y' THEN (some date) and SQL cannot do an implicit conversion of all values, then you're toast.
If you're doing a cased ordering, then the data types have to be compatible with each other.
try this for the date:
Convert(int, TripDate , 112)
A format of 112 will give you yyyymmdd, which is useful in ordering by date as an integer. Use 1 - [date] for descending.
This is assuming that the LegacyID is an integer. Otherwise, you can try casting the date to a type SQL_VARIANT
I have a table and the columns on this table contains empty spaces for some records. Now I need to move the data to another table and replace the empty spaces with a NULL value.
I tried to use:
REPLACE(ltrim(rtrim(col1)),' ',NULL)
but it doesn't work. It will convert all of the values of col1 to NULL. I just want to convert only those values that have empty spaces to NULL.
I solved a similar problem using NULLIF function:
UPDATE table
SET col1 = NULLIF(col1, '')
From the T-SQL reference:
NULLIF returns the first expression if the two expressions are not equal. If the expressions are equal, NULLIF returns a null value of the type of the first expression.
Did you try this?
UPDATE table
SET col1 = NULL
WHERE col1 = ''
As the commenters point out, you don't have to do ltrim() or rtrim(), and NULL columns will not match ''.
SQL Server ignores trailing whitespace when comparing strings, so ' ' = ''. Just use the following query for your update
UPDATE table
SET col1 = NULL
WHERE col1 = ''
NULL values in your table will stay NULL, and col1s with any number on space only characters will be changed to NULL.
If you want to do it during your copy from one table to another, use this:
INSERT INTO newtable ( col1, othercolumn )
SELECT
NULLIF(col1, ''),
othercolumn
FROM table
This code generates some SQL which can achieve this on every table and column in the database:
SELECT
'UPDATE ['+T.TABLE_SCHEMA+'].[' + T.TABLE_NAME + '] SET [' + COLUMN_NAME + '] = NULL
WHERE [' + COLUMN_NAME + '] = '''''
FROM
INFORMATION_SCHEMA.columns C
INNER JOIN
INFORMATION_SCHEMA.TABLES T ON C.TABLE_NAME=T.TABLE_NAME AND C.TABLE_SCHEMA=T.TABLE_SCHEMA
WHERE
DATA_TYPE IN ('char','nchar','varchar','nvarchar')
AND C.IS_NULLABLE='YES'
AND T.TABLE_TYPE='BASE TABLE'
A case statement should do the trick when selecting from your source table:
CASE
WHEN col1 = ' ' THEN NULL
ELSE col1
END col1
Also, one thing to note is that your LTRIM and RTRIM reduce the value from a space (' ') to blank (''). If you need to remove white space, then the case statement should be modified appropriately:
CASE
WHEN LTRIM(RTRIM(col1)) = '' THEN NULL
ELSE LTRIM(RTRIM(col1))
END col1
Maybe something like this?
UPDATE [MyTable]
SET [SomeField] = NULL
WHERE [SomeField] is not NULL
AND LEN(LTRIM(RTRIM([SomeField]))) = 0
here's a regex one for ya.
update table
set col1=null
where col1 not like '%[a-z,0-9]%'
essentially finds any columns that dont have letters or numbers in them and sets it to null. might have to update if you have columns with just special characters.