SQL Server doesn't have as good pattern matching abilities as regular expressions. You can search for the pattern:
[/\\][0-9]%[/\\]
That is, slash followed by a digit followed by any other string followed by a slash. This will match any characters after the first digit, but your examples have nothing of the form /1abc/.
If this is sufficient, then this does the trick:
select v.*,
left(v2.str2, patindex('%[/\\]%', v2.str2) - 1)
from (values ('\\servername\folder1\FTP\folder2\512/862450_FileBundle.zip')) v(str) cross apply
(values (stuff(v.str, 1, patindex('%[/\\][0-9]%[/\\]%', v.str), ''))) v2(str2)
Answer from Gordon Linoff on Stack OverflowSQL Server doesn't have as good pattern matching abilities as regular expressions. You can search for the pattern:
[/\\][0-9]%[/\\]
That is, slash followed by a digit followed by any other string followed by a slash. This will match any characters after the first digit, but your examples have nothing of the form /1abc/.
If this is sufficient, then this does the trick:
select v.*,
left(v2.str2, patindex('%[/\\]%', v2.str2) - 1)
from (values ('\\servername\folder1\FTP\folder2\512/862450_FileBundle.zip')) v(str) cross apply
(values (stuff(v.str, 1, patindex('%[/\\][0-9]%[/\\]%', v.str), ''))) v2(str2)
Other than writing a UDF to loop through the characters, the only thing I can think of is brute force approach...
(The User Defined Function might be your least worst option.)
https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=face1befe5e7c74f457846fc37eca649
SELECT
*,
SUBSTRING(test.unc_file_path, headMatch.pos+1, headMatch.chars)
FROM
test
OUTER APPLY
(
SELECT
MIN(pos), MIN(chars)
FROM
(
SELECT
PATINDEX('%' + head + body + tail + '%', test.unc_file_path) AS pos, chars
FROM
(
SELECT '\'
UNION ALL SELECT '/'
)
head(head)
CROSS JOIN
(
SELECT 1, '[0-9]'
UNION ALL SELECT 2, '[0-9][0-9]'
UNION ALL SELECT 3, '[0-9][0-9][0-9]'
UNION ALL SELECT 4, '[0-9][0-9][0-9][0-9]'
UNION ALL SELECT 5, '[0-9][0-9][0-9][0-9][0-9]'
)
body(chars, body)
CROSS JOIN
(
SELECT '\'
UNION ALL SELECT '/'
)
tail(tail)
)
match
WHERE
pos > 0
)
headMatch(pos, chars)
regex - How to extract Specific Numbers from String in SQL - Stack Overflow
Help Extracting Number Code from String
Regex - extracting numbers from string in Oracle SQL - Stack Overflow
sql - Query to get only numbers from a string - Stack Overflow
You'd use REGEXP_REPLACE in order to remove all non-digit characters from a string:
select regexp_replace(column_name, '[^0-9]', '')
from mytable;
or
select regexp_replace(column_name, '[^[:digit:]]', '')
from mytable;
Of course you can write a function extract_number. It seems a bit like overkill though, to write a funtion that consists of only one function call itself.
create function extract_number(in_number varchar2) return varchar2 is
begin
return regexp_replace(in_number, '[^[:digit:]]', '');
end;
You can use regular expressions for extracting the number from string. Lets check it. Suppose this is the string mixing text and numbers 'stack12345overflow569'. This one should work:
select regexp_replace('stack12345overflow569', '[[:alpha:]]|_') as numbers from dual;
which will return "12345569".
also you can use this one:
select regexp_replace('stack12345overflow569', '[^0-9]', '') as numbers,
regexp_replace('Stack12345OverFlow569', '[^a-z and ^A-Z]', '') as characters
from dual
which will return "12345569" for numbers and "StackOverFlow" for characters.
I am struggling with extracting a number code from a string. My problem is that the string has varying lengths also the code has varying lengths. Any advice on how I can extract the number code within the parenthesis will be greatly appreciated. Below is sample data with expected output.
You can use a regular expression and a correlated hierarchical query to get the values:
Oracle Setup:
CREATE TABLE table_name ( id, value ) AS
SELECT 1, '[ 6d (1.5h; 31h)] x (5 to 7)' FROM DUAL UNION ALL
SELECT 2, '[ 1d (8h; 24h; 48.5h; 72h; 96h)] x (1 to 5)' FROM DUAL;
Query:
SELECT id, COLUMN_VALUE
FROM table_name t
CROSS JOIN
TABLE(
CAST(
MULTISET(
SELECT REGEXP_SUBSTR( t.value, '\d+\.?\d*', 1, LEVEL )
FROM DUAL
CONNECT BY LEVEL <= REGEXP_COUNT( t.value, '\d+\.?\d*' )
) AS SYS.ODCINUMBERLIST
)
) n;
Results:
ID COLUMN_VALUE
--- ------------
1 6
1 1.5
1 31
1 5
1 7
2 1
2 8
2 24
2 48.5
2 72
2 96
2 1
2 5
Query 2:
SELECT REGEXP_SUBSTR( value, '\[\s*([0-9.]+)d\s*\((.*?)\)\]\s*x\s*\(([0-9.]+)\s*to\s*([0-9.]+)\)', 1, 1, NULL, 1 ) AS days,
REGEXP_REPLACE(
REGEXP_SUBSTR( value, '\[\s*([0-9.]+)d\s*\((.*?)\)\]\s*x\s*\(([0-9.]+)\s*to\s*([0-9.]+)\)', 1, 1, NULL, 2 ),
'[^0-9.;]'
)AS hours,
REGEXP_SUBSTR( value, '\[\s*([0-9.]+)d\s*\((.*?)\)\]\s*x\s*\(([0-9.]+)\s*to\s*([0-9.]+)\)', 1, 1, NULL, 3 ) AS x_from,
REGEXP_SUBSTR( value, '\[\s*([0-9.]+)d\s*\((.*?)\)\]\s*x\s*\(([0-9.]+)\s*to\s*([0-9.]+)\)', 1, 1, NULL, 4 ) AS x_to
FROM table_name t;
Results:
DAYS HOURS X_FROM X_TO
---- --------------- ------ ----
6 1.5;31 5 7
1 8;24;48.5;72;96 1 5
You may derive all digits seperated by a delimiter(pipes in this case) by the contribution of regexp_replace as in the following way :
select regexp_replace('[ 6d (1.5h; 31h)] x (5 to 7)','[^0-9.]+','|') str from dual union all
select regexp_replace('[ 1d (8h; 24h; 48.5h; 72h; 96h)] x (1 to 5)','[^0-9.]+','|') from dual;
STR
------------------
|6|1.5|31|5|7|
|1|8|24|48.5|72|96|1|5|
Here's the example with PATINDEX:
select SUBSTRING(fieldName, PATINDEX('%[0-9]%', fieldName), LEN(fieldName))
This assumes (1) the field WILL have a numeric, (2) the numerics are all grouped together, and (3) the numerics don't have any subsequent characters after them.
Extract only numbers (without using while loop) and check each and every character to see if it is a number and extract it
Declare @s varchar(100),@result varchar(100)
set @s='as4khd0939sdf78'
set @result=''
select
@result=@result+
case when number like '[0-9]' then number else '' end from
(
select substring(@s,number,1) as number from
(
select number from master..spt_values
where type='p' and number between 1 and len(@s)
) as t
) as t
select @result as only_numbers