find if there is a 6 digit number within a string - sql

How would you advise to find out in Sql Server 2010/2012 if a query contains a substring equal to a 6 digits number?
e.g. "agh123456 dfsdfdf" matches the requirements
"x123 ddd456" doesn't match the requirements because the 6 digits are not consecutive
"lm123" doesn't match the requirements because only 3 digits are found (out of the required 6)
The problem I encountered so far: is that SUBSTRING as a function requires parameters (position where the number presumably starts and this is random)
while PATINDEX returns the location of a pattern in a string, but we don't know the exact pattern (it can be any 6 digit number)
Any pointers or advice, much appreciated.
Thank you

You can use the LIKE operator:
SELECT *
FROM MyTable
WHERE Mycolumn LIKE '%[0-9][0-9][0-9][0-9][0-9][0-9]%'

Even this should work.. considering you don't have a string like this
abc123 abc123456
Try this
DECLARE #str varchar(max) = 'abcxyz123456'
SELECT ISNUMERIC(SUBSTRING(#str,(SELECT PATINDEX('%[0-9]%',#str)),6))

If you want to select all rows in the table and mask the first 6-digit substring in each row:
DECLARE #mask varchar(max) = '######'
DECLARE #pattern varchar(max) = '%'+REPLACE(#mask,'#','[0-9]')+'%'
SELECT
ISNULL(STUFF(col1,PATINDEX(#pattern,col1),LEN(#mask),#mask),col1)
FROM Table1

Related

Is there any way to look for and extract a string consisting of 2 characters followed by any 8 digit number in SQL Server?

I am trying to create a query to extract a 10 digit string from a larger string. This string would consist of two characters followed by 8 digits e.g.'EL12345678'
I was previously using the below query, where the variable #prefix can consist of any two characters. However i have come across some cases where these characters are used elsewhere within the string causing it to extract the wrong code.
SELECT SUBSTRING(message_key, (SELECT CHARINDEX(#prefix, message_key)), 10) AS pcn,
Message_ID
FROM MQ
WHERE Message_Status != 'processed'
AND Message_Status != 'bad'
AND message_status != 'new'
AND Message_Time > DATEADD(DAY, -#days, dbo.dateonlyVB())
AND Message_MethodName = CASE WHEN #prefix = 'DN' THEN 'SaveJob' ELSE 'savedetails' END;
I tried to use patindex and some wildcards to see if i could specify that it was a number that followed the variable, however this didn't seem to work when i tried it.
I am expecting it to be able to extract a string something like 'EL12345678' from a larger string which can be anywhere in the region of 300+ characters long. However my query is currently occasionally extracting strings like 'elValvef":' instead.
Any help with this at all would be greatly appreciated!
Use can use patindex():
select substring(largerstring,
patindex('%__[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]%', largerstring
), 10
)
UPDATED BASED ON OP COMMENTS
As Gordon showed, you can do this:
SELECT item = SUBSTRING(#string,PATINDEX('%'+#prefix+'[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]%', #string),8)
You can also use NGrams8k for this kind of thing:
DECLARE #string VARCHAR(1000) = 'ABCXXXAB12345678 blah blah', #prefix VARCHAR(2) = 'AB';
SELECT item = ng.token
FROM dbo.NGrams8k(#string,10) AS ng
WHERE PATINDEX('%'+#prefix+'[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]%',ng.token) = 1;
OLD:
This string would consist of two characters followed by 8 digits
e.g.'EL12345678'
If it's that simple you can just do this:
DECLARE #string VARCHAR(1000) = 'EL12345678';
SELECT SUBSTRING(#string,3,8)
--Returns: 12345678

How to get number from a string in sql

I have a string like this 'sdf,11-df,12-asd,sadfsdf'. But I need only numbers from this string in multiple rows like this.
11
12
I need numbers between (,) and (-) that's the actual requirement. String can be like 'sd47f,11-df,12-asd,sadfsdf,12-ds,32-fsdfsd' anything, But numbers will always between (,) and (-)
or find numbers between (,) and (-) it will also help me.
Thanks in advance.
I need any solution guys please help,
Following will work with SQL Server 2016 or higher:
DECLARE #str varchar(50) = 'sd47f,11-df,12-asd,sadfsdf,12-ds,32-fsdfsd'
SELECT
LEFT(Value, CHARINDEX('-', Value)-1)
FROM STRING_SPLIT(#str, ',')
WHERE PATINDEX('%[0-9]-%',Value) > 0
try this
DECLARE #data nvarchar(max) = 'sdf,11-df,12-asd,sadfsdf'
select substring(#data,PATINDEX('%[0-9]%',#data),2)
union all
select substring(#data,PATINDEX('%[-]%',REVERSE(#data))-1,2)
Update
You can also use a function which returns as a table
CREATE FUNCTION dbo.udf_GetNumeric (#strAlphaNumeric VARCHAR(256))
RETURNS TABLE AS RETURN ( select LEFT(value,2) as Value from
string_split(#strAlphaNumeric,',') where PATINDEX('%[0-9]-%',value)
> 0 )
END GO
SELECT * from
dbo.udf_GetNumeric('sd47f,11-df,12-asd,sadfsdf,12-ds,32-fsdfsd')

Separate numeric inside string variable using patindex

I have here a short problem.
i have a value like this
1/11
11/1
11/11
111/1
111/11
i'm trying to separate those value and put them into numeric variable.
let say for example i have numericvar1 and numericvar2
so in the 1st string numericvar1 will contain 1 and numericvar2 will contain 11
and so on.
i've tried it like this
SET #numericvar1= LEFT(#StrNumHolder, PATINDEX('%[0-9][^0-9]%', #StrNumHolder ))
SET #numericvar2= REPLACE(RIGHT(#StrNumHolder, PATINDEX('%[0-9][^0-9]%', #StrNumHolder )),'/','')
in this code if the first number before / is in 2 digit i got the correct output. But if the first number is in 1 digit and the next number is in 2 digit like 1/11 i got the wrong output. something like this var1 = 1 and var2 = 1
did something wrong in my code? or it is not possible? please help me.
You can use CHARINDEX to get the position of '/' then use SUBSTRING to separate the numbers. Here how you can query it:
DECLARE #nIndex INT
SELECT #nIndex = CHARINDEX('/',#StrNumHolder)
SET #numericvar1 = SELECT SUBSTRING(#StrNumHolder,1,#nIndex-1)
SET #numericvar2 = SELECT SUBSTRING(#StrNumHolder,#nIndex+1,LEN(#StrNumHolder))
Can you try something like this?
DECLARE #STRNUMHOLDER VARCHAR(20)
SET #STRNUMHOLDER='111/1'
DECLARE #pos INT
SET #pos = CHARINDEX('/', #STRNUMHOLDER)
SELECT #STRNUMHOLDER AS ORIG, LEFT(#STRNUMHOLDER, #pos-1) AS NUM1, SUBSTRING(#STRNUMHOLDER, #pos+1,99) AS NUM2

Simple Explanation for PATINDEX

I have have been reading up on PATINDEX attempting to understand what and why. I understand the when using the wildcards it will return an INT as to where that character(s) appears/starts. So:
SELECT PATINDEX('%b%', '123b') -- returns 4
However I am looking to see if someone can explain the reason as to why you would use this in a simple(ish) way. I have read some other forums but it just is not sinking in to be honest.
Are you asking for realistic use-cases? I can think of two, real-life use-cases that I've had at work where PATINDEX() was my best option.
I had to import a text-file and parse it for INSERT INTO later on. But these files sometimes had numbers in this format: 00000-59. If you try CAST('00000-59' AS INT) you'll get an error. So I needed code that would parse 00000-59 to -59 but also 00000159 to 159 etc. The - could be anywhere, or it could simply not be there at all. This is what I did:
DECLARE #my_var VARCHAR(255) = '00000-59', #my_int INT
SET #my_var = STUFF(#my_var, 1, PATINDEX('%[^0]%', #my_var)-1, '')
SET #my_int = CAST(#my_var AS INT)
[^0] in this case means "any character that isn't a 0". So PATINDEX() tells me when the 0's end, regardless of whether that's because of a - or a number.
The second use-case I've had was checking whether an IBAN number was correct. In order to do that, any letters in the IBAN need to be changed to a corresponding number (A=10, B=11, etc...). I did something like this (incomplete but you get the idea):
SET #i = PATINDEX('%[^0-9]%', #IBAN)
WHILE #i <> 0 BEGIN
SET #num = UNICODE(SUBSTRING(#IBAN, #i, 1))-55
SET #IBAN = STUFF(#IBAN, #i, 1, CAST(#num AS VARCHAR(2))
SET #i = PATINDEX('%[^0-9]%', #IBAN)
END
So again, I'm not concerned with finding exactly the letter A or B etc. I'm just finding anything that isn't a number and converting it.
PATINDEX is roughly equivalent to CHARINDEX except that it returns the position of a pattern instead of single character. Examples:
Check if a string contains at least one digit:
SELECT PATINDEX('%[0-9]%', 'Hello') -- 0
SELECT PATINDEX('%[0-9]%', 'H3110') -- 2
Extract numeric portion from a string:
SELECT SUBSTRING('12345', PATINDEX('%[0-9]%', '12345'), 100) -- 12345
SELECT SUBSTRING('x2345', PATINDEX('%[0-9]%', 'x2345'), 100) -- 2345
SELECT SUBSTRING('xx345', PATINDEX('%[0-9]%', 'xx345'), 100) -- 345
Quoted from PATINDEX (Transact-SQL)
The following example uses % and _ wildcards to find the position at
which the pattern 'en', followed by any one character and 'ure' starts
in the specified string (index starts at 1):
SELECT PATINDEX('%en_ure%', 'please ensure the door is locked');
Here is the result set.
8
You'd use the PATINDEX function when you want to know at which character position a pattern begins in an expression of a valid text or character data type.

A SQL Problem. Check condition with in a comma seperated value

I have a vairable
DECLARE #AssignOn nvarchar(20)='0,2,5'
I want to check a condition like this
DECLARE #index int
SET DATEFIRST 7
SELECT #index=DATEPART(DW, GETDATE())-1
IF(CONVERT(nvarchar(2),#index) IN #AssignOn)
IN cannot be used here . Any other methods to do this INLINE
You can use CharIndex to find if you have a match. It returns a non zero value if the first string appears in the second.
IF(CHARINDEX(CONVERT(nvarchar(2),#index), #AssignOn) > 0)
The easiest way to do this is to search for the substring ',needle,' in the csv list string. However, this doesn't work correctly for the first and last elements. This can be overcome by concatenating a comma onto each side of the csv list string.
An example in SQL might be:
SELECT
CHARINDEX(','+ NEEDLE +',', ','+ HAYSTACK +',')
FROM table;
Or using LIKE:
SELECT *
FROM table
WHERE ','+ HAYSTACK +',' LIKE '%,'+ NEEDLE +',';
IF CHARINDEX(','+CONVERT(nvarchar(2),#index)+',', ','+#AssignOn+',') <> 0
As you actually define the values in the code you could instead;
DECLARE #AssignOn TABLE (value int)
INSERT #AssignOn VALUES (0),(2),(5)
... #index IN (SELECT value FROM #AssignOn)