Error with SELECT CASE with regular expression - sql-server

I wrote the following query in T-SQL for SQL Server
SELECT
CASE
WHEN ADDR_LINE_1 REGEXP '^[0-9]'
THEN SUBSTRING(ADDR_LINE_1,1,CHARINDEX(' ',ADDR_LINE_1))
ELSE NULL
END AS HOUSE_NUMBER
FROM CUSTOMER
What I want is that if the column ADDR_LINE_1 starts with a number, I want to extract the HOUSE_NUMBER from it. But right now my query gives a parse error. If I replace the word REGEXP with LIKE, the parse error goes away, but I always get NULL for HOUSE_NUMBER. What is the correct syntax for my query?

You could use ISNUMERIC and LEFT like this.
SELECT
CASE WHEN ISNUMERIC(LEFT(ADDR_LINE_1, 1)) = 1
THEN SUBSTRING(ADDR_LINE_1, 1, CHARINDEX(' ', ADDR_LINE_1))
ELSE NULL
END AS HOUSE_NUMBER
FROM CUSTOMER

How about using the LIKE
SELECT
CASE
WHEN ADDR_LINE_1 Like '%[0-9]%'
THEN SUBSTRING(ADDR_LINE_1,1,CHARINDEX(' ',ADDR_LINE_1))
ELSE NULL
END AS HOUSE_NUMBER
FROM CUSTOMER

Related

Date format is not recognized Snowflake

view in snowflake as follows;
CREATE OR REPLACE VIEW A AS(
SELECT tab1.colA,
tab1.colB,
CASE WHEN COALESCE(DATE_ACT_CREATED,'missing')='missing' THEN DATE ('1970-01- 01') ELSE TO_DATE(DATE_ACT_CREATED) END AS ACT_CREATED_DATE
FROM tab1);
Please note that because of some reasons, column DATE_ACT_CREATED was defined as varchar earlier. This view is created fine. But when I try to retrieve records from it;
SELECT * FROM viewA;
I get following error,
Date '' is not recognized
But when I take out the entry; CASE WHEN COALESCE(DATE_ACT_CREATED,'missing')='missing' THEN DATE ('1970-01- 01') ELSE TO_DATE(DATE_ACT_CREATED) END AS ACT_CREATED_DATE the error is gone.
May I know how can I handle this date error issue? Found this link enter link description here, but it couldn't help much.
Help is appreciated.
You get the error because the case when DATE_ACT_CREATED is an empty string is not handled in your CASE condition. So the TO_DATE function couldn't work.
You should try TRY_TO_DATE. If your entry couldn't be casted as a date then it returns null that will be handled with your COALESCE.
CREATE OR REPLACE viewA AS(
SELECT
tab1.colA,
tab1.colB,
COALESCE(TRY_TO_DATE(DATE_ACT_CREATED), DATE('1970-01- 01')) AS ACT_CREATED_DATE
FROM tab1);
Using the following query you will not get the error if the input is ''(Empty string), actual date, NULL keyword, or missing keyword.
CREATE OR REPLACE VIEW A
AS
SELECT COL1, COL2,
CASE WHEN COALESCE(DATE_AT_CREATED, '') = '' THEN DATE('1970-01-02')
ELSE CASE WHEN DATE_AT_CREATED = 'missing' THEN DATE('1970-01-02') ELSE TO_DATE(DATE_AT_CREATED) END
END AS ACT_CREATED_DATE
FROM TAB1;
SELECT * FROM A;

Why the result is still null after placing the condition also? [duplicate]

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

How to select a column value in to a case statement for a result of another column in the same table

This is a very simplified vision of the statement
SELECT
ChangeId,
ColumnName,
BeforeChange,
CASE ColumnName
WHEN 'x' THEN AfterChange ELSE 'dbo.function(Y)'
END AS AfterChange,
AfterChangeUpdateId,
UpdatedBy,
ChangeDate,
ChangeType
FROM
[DEV].[dbo].[tblperson_Audit]
Not sure this is possible but I want to pass the ColumnName value in to the CASE statment to show different results depending upon the value for every row.
The function passes a value for an integer.
Any help would be great thanks
Can you try this? It is assumed that the function returns single value
SELECT ChangeId,
ColumnName,
BeforeChange,
CASE ColumnName WHEN 'x' THEN AfterChange ELSE dbo.function(ColumnName) END AS AfterChange,
AfterChangeUpdateId,
UpdatedBy,
ChangeDate,
ChangeType
FROM [DEV].[dbo].[tblperson_Audit]
Slight syntax error in Madhivanan's solution. It should be:
case when condition() then column1 else column2 end as columnname
So in your example:
CASE WHEN 'x' THEN AfterChange ELSE 'dbo.function(Y)' as AfterChange
SQL Server's conditional syntax always seems so counter-intutive and weird I have to Google it every time...

SQL Server LIKE search with [ ] not matching as expected

I'm trying to search the contents of a text column in a SQL Server DB. I do not have the ability to add a fulltext index to the column, so I'm trying to do so in a query:
SELECT t.DateBegin, t.Action, t.Detail, t.Status, t.ErrorText,
CASE WHEN t.ErrorText LIKE '%[IBM][CLI Driver][DB2/LINUXX8664]%' THEN 'IBM'
WHEN t.ErrorText LIKE '%WebApplicationContainerServer%' THEN 'WACS'
ELSE '' END AS ErrorType
FROM (
SELECT a.DateBegin, a.Action, a.Detail, a.Status,
CONVERT(varchar(max),
REPLACE(REPLACE(CAST(a.ExtInfo AS varchar(max)), CHAR(13), ' '), CHAR(10), ' ')
) as ErrorText
FROM bi4infoburst.dbo.IBT_RTS_ACTION a
WHERE a.DateBegin >= DATEADD(day, -7, GETDATE())
AND a.Status = 5
) t
ORDER BY t.DateBegin
My thought here is that if I converted it to a varchar then I could use the LIKE operator. But when I run this query, it always matches the first case regardless of what text or pattern I put in.
What am I doing wrong?
It is an issue with character escaping.
Square brackets have to be handled properly because otherwise are interpreted as special chars like % is; using square brackets you match any of the char inside the brackets and that's why the first CASE always matches.
The solution is to to declare an escape character in the statement to escape the brackets.
If used in a WHERE clause the syntax would be as follows:
WHERE t.ErrorText LIKE '%![IBM!]![CLI Driver!]![DB2/LINUXX8664!]%' ESCAPE '!'
I don't know if is possible and how to use it in a CASE statement...

check if value in column is date, and then do something with it

I have a column that holds a rejected reason for a person.
The value is either something like "Person refused" or "10/18/2012"
I'm trying to setup my query to check if the value is a date, then it can put a blank space in its place. Otherwise, keep the text that's in there.
The query that I setup is:
SELECT DISTINCT person_id,
CASE description
WHEN ISDATE(description) THEN ''
END AS refuseReason
FROM person
But this returns an error. If the dates themselves are saved as VARCHAR, then would I have to convert them first to a date, then check to see if ISDATE? If I did that, would it convert the text when it comes accross that?
EDIT: I tried it by casting it to datetime, and i keep getting error as well:
SELECT DISTINCT person_id,
CASE description
WHEN ISDATE(CAST(OBSVALUE AS DATETIME)) THEN ''
END AS refuseReason
FROM person
(Assuming TSQL) IsDate() returns 1 or 0. (Also your CASE syntax was incorrect)
Try:
SELECT DISTINCT person_id,
CASE
WHEN ISDATE(description) = 1 THEN ''
ELSE description
END AS refuseReason
FROM person
The ISDATE() functions returns a boolean 1 or 0
you have to make the clause by using
WHEN ISDATE(#variable) = 1 THEN ''
ELSE #variable

Resources