Using CHARINDEX and SUBSTRING in a CASE statement - sql-server

I need to evaluate a field with a CASE statement. The field name is Commodity and is a varchar(255). The values differ and I need to extract a specific portion from it after a specific character. The character is a '>'. I was able to come up with the value I want returned after the > by using the following code:
SUBSTRING(Commodity, CHARINDEX('>', Commodity) + 2, LEN(Commodity))
I am however unsure of how to work this into my CASE statement. I need to test for Is Null and then just assign it a value of 'No Commodity'. Then I need to test for the presence of a > and then implement the code above to return the value. Then I need to test for when there is no > but it is not null and just return the value of the Commodity field.

You just need to have these three conditions in when clauses. You can use charindex to make sure the > character exists in the string:
CASE
WHEN commodity IS NULL THEN 'No Comodity'
WHEN CHARINDEX('>', Commodity) > 0 THEN
SUBSTRING(commodity, CHARINDEX('>', commodity) + 2, LEN(commodity))
ELSE comodity
END

Related

My program crashes when I try to read a NULL value using sqlite in C

I have tried to use the below statement to check if the value present in the given fieldname for a record is NULL or not, if it is NULL then put 0 else return the value present in the fieldname.
It shows syntax error.
SELECT [structname.fieldname], isnull([structname.fieldname],0) FROM tablename WHERE condition;
Can you please let me know where am I going wrong?
I have also tried the below statement
SELECT [structname.fieldname], CASE WHEN [structname.fieldname] IS NULL THEN 0 ELSE [structname.fieldname] END FROM tablename WHERE condition;
For the above statement, the program crashes when it encounters a NULL value. Can you please tell me how else can I check if a value of a particular record is NULL or not and then read the value if it is not NULL else read it as 0
You are not using correctly the square brackets.
The column names should be written like:
[structname].[fieldname]
assuming that [structname] is the name or the alias of the table where fieldname comes from, and not like:
[structname.fieldname]
which would be ok only if the column's name is actually structname.fieldname.
What you need can be done with the function COALESCE():
SELECT COALESCE([fieldname], 0) FROM tablename

SQL String are same but case equals method returns false

I am using SQL to compare two columns and return TRUE/FALSE if they are equal.
In some cases, the two columns contain exactly the same string (no spaces or anything) but I am still getting false.
What may the reason for this be?
I am using this code:
CASE WHEN column1 = column2 THEN 0 ELSE 1 END AS [check]
The values are different despite the displayed value.
Using T-SQL, run a query like this to see the exact difference in the underlying raw values:
SELECT
column1
, CAST(column1 AS varbinary(MAX)) AS column1Binary
, column2
, CAST(column2 AS varbinary(MAX)) AS column2Binary
FROM dbo.YourTable;
This will reveal underlying differences like tabs or subtle character differences.
In fact, a likely explanation for what you are seeing is that one/both of the strings has leading and/or trailing whitespace. On SQL Server you may try:
CASE WHEN LTRIM(column1) = LTRIM(column2) THEN 0 ELSE 1 END AS [check]
If the above does not detect the problematical records, then try checking the length:
CASE WHEN LEN(column1) = LEN(column2) THEN 0 ELSE 1 END AS [check2]

Error converting varchar to bigint in very peculiar situation

My intent is to retrieve all CLIENT_CODE converted to BigInt, to compare with a value passed as a parameter in the where clause from a 400 lines sql query. When execute the code below, I get the following error message:
message error 8114 from sql server: "Error converting varchar to
bigint".
Test Code:
select CASE when (len (CLIENT_CODE) > 2 and isNumeric(CLIENT_CODE) = 1)
then (CAST(SUBSTRING(TAB.CLIENT_CODE, 1, LEN(TAB.CLIENT_CODE)-1) AS BIGINT))
else CLIENT_CODE end from TABLE TAB
Code Nested:
--HUGE_SQL...
AND ((CASE when (len (CLIENT_CODE) > 2 and isNumeric(CLIENT_CODE) = 1)
then (CAST(SUBSTRING(TAB.CLIENT_CODE, 1, LEN(TAB.CLIENT_CODE)-1) AS BIGINT))
else CLIENT_CODE end) = #MyClient_Code)
--... HUGE_SQL
Our CLIENT_CODE is varchar(20), some have 0 characters, and some have letters, but almost every record is a number.
In my understanding, the case must be evaluated first, but it don't appear to be the case.
When i put the isNumeric(CLIENT_CODE) = 1 in the where clause, in test code, it works. My problem is that i can't do it in this particular case, because the fact it is already nested in the where clause from a huge sql query, and adding the isNumeric(CLIENT_CODE) = 1 there doesn't work, because it has a lot of other conditions.
Which is the best way to retrieve this data? Can someone figure it out how to do it?
(It will be very helpfull some kind of explanation of how is treated the functions vs case vs where)
Your Case expression Returns BIGINT in one case and else it return VARCHAR data type .
For Case expression, in each case the returned data type must be same.
Also instead of using ISNUMERIC() use following
select CASE
when (len (CLIENT_CODE) > 2 and CLIENT_CODE NOT LIKE '%[^0-9]%')
then (CAST(SUBSTRING(TAB.CLIENT_CODE, 1, LEN(TAB.CLIENT_CODE)-1) AS BIGINT))
end
from TABLE TAB
ISNUMERIC() returns true for values like 123a1 , 346g2 it considers it as raise to power stuff, therefore use NOT LIKE '%[^0-9]%' to get strings where only actual numeric values are present.

Parsing Chars In SQL Using PATINDEX

I'm trying to validate a string using raw sql;
tried using:
DECLARE #AlphaNumeric varchar(50)
SET #AlphaNumeric = '1017a'
SELECT SUBSTRING(#AlphaNumeric, 1, (PATINDEX('%[^0-9]%', #AlphaNumeric) - 1)) AS 'Numeric',
SUBSTRING(#AlphaNumeric, PATINDEX('%[^0-9]%', #AlphaNumeric), DATALENGTH(#AlphaNumeric)) AS 'Alpha'
But if the user types 101a7a,this doesnt work properly;what i want to do exactly is;
I want the variable always to be, numeric+alphanumeric,lenght doesnt matter.
For example :
2303A OK
23A434A NOT OK
A344 NOT OK.
4324AAC OK
This would be dead easy if i could do it in Regex but sql gives me headaches :(
Letters followed by numbers are OK; Numbers followed by letters aren't; All characters must be letters or numbers. Hence...
select * from yourtable
where yourfield like '%[0-9][a-z]%'
and not (yourfield like '%[a-z][0-9]%')
and not (yourfield like '%[^0-9a-z]%')
I think this will do what you want. At least, it works on your sample data:
with t as (
select '2303A' as col union all
select '23A434A' union all
select 'A344'
)
select *,
(case when col like '%[0-9]%' and
substring(col, patindex('%[A-Z]%', col), len(col)) not like '%[^A-Z]%'
then 'OK'
else 'NOT OK'
end)
from t;
The two conditions are. First check that the character string has a number somewhere. Then, check that there are only letters after the first letter is found. I'm assuming that all letters are uppercase.
EDIT:
There might be an easier way. You can check that a number is followed by a letter somewhere in the string, but that a letter is never followed by a number. For this, you only need like:
select (case when col not like '%[^A-Z0-9]%' and
col like '%[0-9][A-Z]%' and
col not like '%[A-Z][0-9]%'
then 'OK'
else 'NOT OK'
end)
I have an approach that should work in your situation. Basically identify the position of the last integer and compare it to the position of the first non integer. You can get the position of the last integer like this
len(#AlphaNumeric) - PATINDEX('%[0-9]%', Reverse(#AlphaNumeric))+1
and you can get the position of the first non integer like this
PATINDEX('%[^0-9]%', #AlphaNumeric)
so that would make your where clause (where all integers precede any non integers like this
Where (len(#AlphaNumeric) - PATINDEX('%[0-9]%', Reverse(#AlphaNumeric))+1 ) < PATINDEX('%[^0-9]%', #AlphaNumeric)

valid record in SQL query

I have a table with few columns and one of the column is DockNumber. I have to display the docknumbers if they confirm to a particular format
First five characters are numbers followed by a - and followed by 5 characters. The last but one character should be a alpha.
12345-678V9
How can I check in SQL if the first 5 characters are numbers and there is a hyphen and next 3 are numbers and last but one is an alpha.
Building on #gbn's answer, this checks to make sure the length is 11 (in case the #val is not a char(11) or varchar(11) and also checks to make sure the second to last char is alpha
DECLARE #val VARCHAR(20)
SET #val = '12345-678V9'
SELECT CASE WHEN LEN(#val) = 11 AND #val LIKE '[0-9][0-9][0-9][0-9][0-9]-[0-9][0-9][0-9][A-Z0-9][0-9]'
THEN 'isMatch'
ELSE 'isNotMatch'
END AS [Valid]
you can use this, you will have to figure it out on how to use this...
SELECT Case when
Cast(ISNUMERIC(LEFT(#Str,5)) as int) + case when substring(#str,6,1)= '-' then 1 else 0 end +case when substring(#str,10,1) like '[a-z]' then 1 else 0 end =3
THEN 'Matched'
Else 'NotMatched'
End
Regular Expressions can be your friend.
LIKE '[0-9][0-9][0-9][0-9][0-9]-[0-9][0-9][0-9][A-Z][0-9]'
Now, this allows lower case a-z too. You'd need to coerce collation if you wanted upper case only
Value COLLATE Latin_General_BIN
LIKE '[0-9][0-9][0-9][0-9][0-9]-[0-9][0-9][0-9][A-Z][0-9]' COLLATE Latin_General_BIN
PATINDEX is probably the ideal solution.
Select ...
From Table
Where PatIndex('[0-9][0-9][0-9][0-9][0-9]-[0-9][0-9][0-9][A-Z][0-9]', DockNumber) > 0
Where DockNumber Like '[0-9][0-9][0-9][0-9][0-9][-][0-9][0-9][0-9][a-z][0-9]
should work, but i would suggest using Regular expression in code. Much easier if it is possible.
The regex should be '^\d{5}-\d{3}[A-Z]\d$', because without ^ and $ it would find longer strings that contain that sequence (122 12345-678V9 34).
Use rule
CREATE RULE pattern_rule
AS
#value LIKE '[0-9][0-9][0-9][0-9]-[0-9][0-9][0-9][0-9][A-Z][0-9]'
Then bind rule to column

Resources