using oracle sql substr to get last digits - sql

I have a result of a query and am supposed to get the final digits of one column say 'term'
The value of column term can be like:
'term' 'number' (output)
---------------------------
xyz012 12
xyz112 112
xyz1 1
xyz02 2
xyz002 2
xyz88 88
Note: Not limited to above scenario's but requirement being last 3 or less characters can be digit
Function I used: to_number(substr(term.name,-3))
(Initially I assumed the requirement as last 3 characters are always digit, But I was wrong)
I am using to_number because if last 3 digits are '012' then number should be '12'
But as one can see in some specific cases like 'xyz88', 'xyz1') would give a
ORA-01722: invalid number
How can I achieve this using substr or regexp_substr ?
Did not explore regexp_substr much.

Using REGEXP_SUBSTR,
select column_name, to_number(regexp_substr(column_name,'\d+$'))
from table_name;
\d matches digits. Along with +, it becomes a group with one or more digits.
$ matches end of line.
Putting it together, this regex extracts a group of digits at the end of a string.
More details here.
Demo here.

Oracle has the function regexp_instr() which does what you want:
select term, cast(substr(term, 1-regexp_instr(reverse(term),'[^0-9]')) as int) as number

select SUBSTRING(acc_no,len(acc_no)-1,len(acc_no)) from table_name;

Related

How to identify combination of number and character in SQL

I have a requirement where I have to find number of records in a special pattern in the field ref_id in a table. It's a varchar column. I need to find all the records where 8th, 9th and 10th character are numeric+XX. That is it should be like 2XX or 8XX. I tried using regexp :digit: but no luck. Essentially I am looking for all records where 8th-10th characters are 1XX, 2XX, 3XX… etc
Using REGEXP_LIKE, replace table with Yours:
SELECT COUNT(*)
FROM table
WHERE REGEXP_LIKE(ref_id,'^.{7}[0-9]XX');
.{7} whatever seven characters
[0-9] 8th character digit
XX 9th and 10th characters X
Or with [:digit:] class as You are mentioning, You may use:
SELECT COUNT(*)
FROM table
WHERE REGEXP_LIKE(ref_id,'^.{7}[[:digit:]]XX');
This can also be achieved using standard non-regex SQL functions
select * from t where s like '________XX%' -- any 8 characters and then XX
AND translate( substr(s,8,1),'?0123456789','?') is null; --8th one is numeric
DEMO
No need for a regexp:
select * from mytable where substr(ref_id, 8, 3) in ('0XX','1XX','2XX','3XX','4XX','5XX','6XX','7XX','8XX','9XX')
or
select * from mytable where substr(ref_id, 8, 3) in ('1XX','2XX','3XX','4XX','5XX','6XX','7XX','8XX','9XX')
I don't know if '0XX' is a valid match or not.
Regexp's tend to be slow.

Regular Expression in oracle 11g how to retrieve data from a column

I have the following data stored in the database column xyz:
a=222223333;b=433333657675457;c=77777;
a=52424252424242;d=5353535353;b=7373737373;
There is no requirement that b value should always be there but if b value is present I have to retrieve the value following b=.
I want to retrieve the value of b using regular expressions in Oracle and I am unable to do it.
Can anyone please help me find a solution for this?
I suggest using Oracle built-in function REGEXP_SUBSTR which returns a substring using regular expressions. According to the example you posted, the following should work.
SELECT REGEXP_SUBSTR(xyz, 'b=\d+;') FROM your_table
You can use regexp_substr:
select substr(regexp_substr(';' || xyz, ';b=\d+'), 4) from your_table;
Concatenation with ; is to distinguish between key-value pair with key say 'ab' and 'b'.
Use a Subexpression to Select a Substring of Your REGEXP_SUBSTR Matching Pattern
My match pattern, 'b=(\d+);', includes the parenthesis which mark this subexpression which is the last parameter of REGEXP_SUBSTR.
If you look at the 12c documentation, you will see that the third example uses a subexpression.
The escaped d just is a regular expression shorthand to indicate that we are looking for digits and the plus symbol is a quantifier indicating 1 or more digits.
SCOTT#db>WITH smple AS (
2 SELECT
3 'a=52424252424242;d=5353535353;b=7373737373;' dta
4 FROM
5 dual
6 ) SELECT
7 dta,
8 regexp_substr(a.dta,'b=(\d+);',1,1,NULL,1) subexp
9 FROM
10 smple a;
DTA subexp
---------------------------------------------------------
a=52424252424242;d=5353535353;b=7373737373; 7373737373
above solution is working in all the cases even if b contains alphanumeric

REGEXP_LIKE between number range

Can someone please finalize the code on the below.
I only want to look for a 6 digit number range anywhere in the RMK field, between 100000 and 999999
REGEXP_LIKE(RMKADH.RMK, '[[:digit:]]')
The current code works but is bringing back anything with a number so I'm trying to narrow it down to 6 digits together. I've tried a few but no luck.
Edit:
I want to flag this field if a 6 digit number is present. The reference will always be 6 digits long only, no more no less. But as it's a free text field it could be anywhere and contain anything.
Example output I do want to flag: >abc123456markj< = flagged.
Output I don't want to flag: >Mark 23647282< because the number it finds is more than 6 characters in length I know it's not a valid reference.
Try this:
REGEXP_LIKE(RMKADH.RMK, '[1-9][[:digit:]]{5}') AND length(RMKADH.RMK) = 6
For more info, see: Multilingual Regular Expression Syntax
You can do a REGEXP_SUBSTR to get 6 digits out of the given field and compare it using between
select * from t
where to_number(regexp_substr(col,'[[:digit:]]{6}')) between 100000 and 999999;
;
Please note that if a bigger sequence than 6 digits exists, the above solution will take first 6 digits into consideration. If you want to do for any 6 consecutive digits, the solution will have to be a different one.
If you want to get all the Records which have only Numeric values in them you can use below query
REGEXP_LIKE(RMKADH.RMK, '^[[:digit:]]+$');
The above will match any number of Numbers from start to end in the string. So if your Numbers span from 1 digit to any number of Digits, this will be useful.
SELECT
to_number(regexp_replace('abc123456markj', '[^[:digit:]]', '')) digits
FROM
dual
WHERE
REGEXP_LIKE('abc123456markj', '[[:digit:]]')
AND
length(regexp_replace('abc123456markj', '[^[:digit:]]', '')) = 6
AND
regexp_replace('abc123456markj', '[^[:digit:]]', '') BETWEEN 100000 AND 999999;

How to Select a substring in Oracle SQL up to a specific character?

Say I have a table column that has results like:
ABC_blahblahblah
DEFGH_moreblahblahblah
IJKLMNOP_moremoremoremore
I would like to be able to write a query that selects this column from said table, but only returns the substring up to the Underscore (_) character. For example:
ABC
DEFGH
IJKLMNOP
The SUBSTRING function doesn't seem to be up to the task because it is position-based and the position of the underscore varies.
I thought about the TRIM function (the RTRIM function specifically):
SELECT RTRIM('listofchars' FROM somecolumn)
FROM sometable
But I'm not sure how I'd get this to work since it only seems to remove a certain list/set of characters and I'm really only after the characters leading up to the Underscore character.
Using a combination of SUBSTR, INSTR, and NVL (for strings without an underscore) will return what you want:
SELECT NVL(SUBSTR('ABC_blah', 0, INSTR('ABC_blah', '_')-1), 'ABC_blah') AS output
FROM DUAL
Result:
output
------
ABC
Use:
SELECT NVL(SUBSTR(t.column, 0, INSTR(t.column, '_')-1), t.column) AS output
FROM YOUR_TABLE t
Reference:
SUBSTR
INSTR
Addendum
If using Oracle10g+, you can use regex via REGEXP_SUBSTR.
This can be done using REGEXP_SUBSTR easily.
Please use
REGEXP_SUBSTR('STRING_EXAMPLE','[^_]+',1,1)
where STRING_EXAMPLE is your string.
Try:
SELECT
REGEXP_SUBSTR('STRING_EXAMPLE','[^_]+',1,1)
from dual
It will solve your problem.
You need to get the position of the first underscore (using INSTR) and then get the part of the string from 1st charecter to (pos-1) using substr.
1 select 'ABC_blahblahblah' test_string,
2 instr('ABC_blahblahblah','_',1,1) position_underscore,
3 substr('ABC_blahblahblah',1,instr('ABC_blahblahblah','_',1,1)-1) result
4* from dual
SQL> /
TEST_STRING POSITION_UNDERSCORE RES
---------------- ------------------ ---
ABC_blahblahblah 4 ABC
Instr documentation
Susbtr Documentation
SELECT REGEXP_SUBSTR('STRING_EXAMPLE','[^_]+',1,1) from dual
is the right answer, as posted by user1717270
If you use INSTR, it will give you the position for a string that assumes it contains "_" in it. What if it doesn't? Well the answer will be 0. Therefore, when you want to print the string, it will print a NULL.
Example: If you want to remove the domain from a "host.domain". In some cases you will only have the short name, i.e. "host". Most likely you would like to print "host". Well, with INSTR it will give you a NULL because it did not find any ".", i.e. it will print from 0 to 0. With REGEXP_SUBSTR you will get the right answer in all cases:
SELECT REGEXP_SUBSTR('HOST.DOMAIN','[^.]+',1,1) from dual;
HOST
and
SELECT REGEXP_SUBSTR('HOST','[^.]+',1,1) from dual;
HOST
Another possibility would be the use of REGEXP_SUBSTR.
In case if String position is not fixed then by below Select statement we can get the expected output.
Table Structure
ID VARCHAR2(100 BYTE)
CLIENT VARCHAR2(4000 BYTE)
Data-
ID CLIENT
1001 {"clientId":"con-bjp","clientName":"ABC","providerId":"SBS"}
1002
--
{"IdType":"AccountNo","Id":"XXXXXXXX3521","ToPricingId":"XXXXXXXX3521","clientId":"Test-Cust","clientName":"MFX"}
Requirement - Search ClientId string in CLIENT column and return the corresponding value. Like From "clientId":"con-bjp" --> con-bjp(Expected output)
select CLIENT,substr(substr(CLIENT,instr(CLIENT,'"clientId":"')+length('"clientId":"')),1,instr(substr(CLIENT,instr(CLIENT,'"clientId":"')+length('"clientId":"')),'"',1 )-1) cut_str from TEST_SC;
--
CLIENT cut_str
----------------------------------------------------------- ----------
{"clientId":"con-bjp","clientName":"ABC","providerId":"SBS"} con-bjp
{"IdType":"AccountNo","Id":"XXXXXXXX3521","ToPricingId":"XXXXXXXX3521","clientId":"Test-Cust","clientName":"MFX"} Test-Cust
Remember this if all your Strings in the column do not have an underscore
(...or else if null value will be the output):
SELECT COALESCE
(SUBSTR("STRING_COLUMN" , 0, INSTR("STRING_COLUMN", '_')-1),
"STRING_COLUMN")
AS OUTPUT FROM DUAL
To find any sub-string from large string:
string_value:=('This is String,Please search string 'Ple');
Then to find the string 'Ple' from String_value we can do as:
select substr(string_value,instr(string_value,'Ple'),length('Ple')) from dual;
You will find result: Ple

How to get rightmost 10 places of a string in oracle

I am trying to fetch an id from an oracle table. It's something like TN0001234567890345. What I want is to sort the values according to the right most 10 positions (e.g. 4567890345). I am using Oracle 11g. Is there any function to cut the rightmost 10 places in Oracle SQL?
You can use SUBSTR function as:
select substr('TN0001234567890345',-10) from dual;
Output:
4567890345
codaddict's solution works if your string is known to be at least as long as the length it is to be trimmed to. However, if you could have shorter strings (e.g. trimming to last 10 characters and one of the strings to trim is 'abc') this returns null which is likely not what you want.
Thus, here's the slightly modified version that will take rightmost 10 characters regardless of length as long as they are present:
select substr(colName, -least(length(colName), 10)) from tableName;
Another way of doing it though more tedious. Use the REVERSE and SUBSTR functions as indicated below:
SELECT REVERSE(SUBSTR(REVERSE('TN0001234567890345'), 1, 10)) FROM DUAL;
The first REVERSE function will return the string 5430987654321000NT.
The SUBSTR function will read our new string 5430987654321000NT from the first character to the tenth character which will return 5430987654.
The last REVERSE function will return our original string minus the first 8 characters i.e. 4567890345
SQL> SELECT SUBSTR('00000000123456789', -10) FROM DUAL;
Result: 0123456789
Yeah this is an old post, but it popped up in the list due to someone editing it for some reason and I was appalled that a regular expression solution was not included! So here's a solution using regex_substr in the order by clause just for an exercise in futility. The regex looks at the last 10 characters in the string:
with tbl(str) as (
select 'TN0001239567890345' from dual union
select 'TN0001234567890345' from dual
)
select str
from tbl
order by to_number(regexp_substr(str, '.{10}$'));
An assumption is made that the ID part of the string is at least 10 digits.