Oracle Substring a column for last index of character - sql

I am trying to do substring in Oracle using last index of a character '_'.
Not able to get it rite. Please see the query which does a substring of second occurrence of "-". But it does not work if the string only has one occurrence of "-".
SELECT NVL(SUBSTR('TEMP_ABC', 0, INSTR('TEMP_ABC', '_',1,2)-1), 'TEMP_ABC')
FROM DUAL
Result - TEMP_ABC
Expected Result - TEMP
SELECT NVL(SUBSTR('TEMP_ABC_XYZ', 0, INSTR('TEMP_ABC_XYZ', '_',1,2)-1), 'TEMP_ABC_XYZ')
FROM DUAL
Result - TEMP_ABC
Expected Result - TEMP_ABC
Any clue on what I am doing wrong here?

In instr function, if you use -1 at the last parameter, it means last occurrence of the char string.
instr(string, '_', -1) = last occurrence of _
Thus:
select substr('TEMP_ABC',1,instr('TEMP_ABC','_',-1)-1)
from dual;
Result: TEMP
select substr('TEMP_ABC_XYZ',1,instr('TEMP_ABC_XYZ','_',-1)-1)
from dual;
Result: TEMP_ABC

Related

Oracle replace some duplicated characters (non digits )

anyone can help me to build proper syntax for regexp_replace to remove any multiplicated non-digits and non-letters from string ? If digit/letter is multiplicated - it is not changed
eg.
source and expected result:
'ABBC000001223, ABC00000212,,, '
'ABBC000001223, ABC00000212, '
(removed second occurance of space after comma and second and third comma )
Use this REGEXP_REPLACE to match any non alphanumeric character in the first group
([^[:alnum:]])
followed by one or more same charcters (group 1)
([^[:alnum:]])(\1)+
and replace it with the original character (group 1)
I added some other data to demonstrate the result
with dta as (
select 'ABBC000001223, ABC00000212,,, ' txt from dual union all
select ',.,;,;;;;,,,,,,,,,,,,#''++`´' txt from dual union all
select 'ABBC000001223ABC00000212' txt from dual)
select txt,
regexp_replace(txt,'([^[:alnum:]])(\1)+', '\1') result
from dta
TXT
-------------------------------
RESULT
--------------------------------
ABBC000001223, ABC00000212,,,
ABBC000001223, ABC00000212,
,.,;,;;;;,,,,,,,,,,,,#'++`´
,.,;,;,#'+`´
ABBC000001223ABC00000212
ABBC000001223ABC00000212

ORA-01722: invalid number - value with two decimals

I'm trying to get the max value from a text field. All but two of the values are numbers with a single decimal. However, two of the values have something like 8.2.10. How can I pull back just the integer value? The values can go higher than 9.n, so I need to convert this field into a number so that I can get the largest value returned. So all I want to get back is the 8 from the 8.2.1.
Select cast(VERSION as int) is bombing out because of those two values with a second . in them.
You may derive by using regexp_substr with \d pattern :
with tab as
(
select regexp_substr('8.2.1', '\d', 1, 1) from dual
union all
select regexp_substr('9.0.1', '\d', 1, 1) from dual
)
select * from tab;
For Oracle you must attend the value as string for retire only the part before the dot. Ex:
SELECT NVL( SUBSTR('8.2.1',0, INSTR('8.2.1','.')-1),'8.2.1') AS SR FROM DUAL;
Check than the value is repeated 3 times in the sentence, and if the value is zero or the value didn't have decimal part then it will return the value as was set.
I had to use T-SQL rather PL/SQL, but the idea is the same:
DECLARE #s VARCHAR(10);
SELECT #s='8.2.1';
SELECT CAST(LEFT(#s, CHARINDEX('.', #s) - 1) AS INT);
returns the integer 8 - note that it won't work if there are no dots because it takes the part of the string to the left of the first dot.
If my quick look at equivalent functions was correct, then in Oracle that would end up as:
SELECT CAST(SUBSTR(VERSION, 1, INSTR(VERSION, '.') - 1) AS INT)

Oracle - Get all characters before the nth occurrence of a character

I am trying to get a query where I get all characters from a string before the 'n'the occurence of a character.
Say I could have the following strings:
'123456,123456,123456'
'123456'
'123456,123456,123456,123456,123456,123456'
'123456,123456,123456,123456,123456,123456,123456'
Now I want my query to always return everything before the 5th occurence of the comma,
Result:
'123456,123456,123456'
'123456'
'123456,123456,123456,123456,123456'
'123456,123456,123456,123456,123456'
I've been trying with some substr or regexes, but I can't get my head around this.
INSTR function has exactly what you need to find the position of n-th substring - see the occurrence parameter.
To get the part of a string till this location use SUBSTRING.
To avoid the case when there is no Nth symbol, use NVL (or COALESCE).
For example (replace 5 with N and insert your columns):
SELECT NVL(
SUBSTR(YOUR_COLUMN, 1,
INSTR(YOUR_COLUMN,',',1,5) -1),
YOUR_COLUMN)
FROM YOUR_TABLE;
You can do that:
define string_value='123456,123456';
select CASE
WHEN (length('&string_value') - length(replace('&string_value',',',null))) >=5
THEN SUBSTR('&string_value',0,INSTR('&string_value',',',1,5)-1)
ELSE '&string_value'
END as output
from dual;
output:
123456,123456
define string_value='123456,123456,123456,123456,123456,123456';
select CASE
WHEN (length('&string_value') - length(replace('&string_value',',',null))) >=5
THEN SUBSTR('&string_value',0,INSTR('&string_value',',',1,5)-1)
ELSE '&string_value'
END as output
from dual;
output:
123456,123456,123456,123456,123456
This will work event if the number of character between the commas is not always the same.

Oracle - REGEXP_SUBSTR leading zeroes ignored issue

While execution below query I'm getting "235" instead of expected results "0"
select REGEXP_SUBSTR(000.235||'', '[^.]+', 1, 1) from dual;
Do this instead, and you'll see where the problem comes:
select 000.235||'' from dual
Result:
.235
The regexp picks up the first longest occurrence of non-period, which in this string is "235", so it's working correctly; it's the input value that is broken
Now, if you'd written it like this, it would be fine:
select REGEXP_SUBSTR('000.235', '[^.]+', 1, 1) from dual
So why the odd presentation of the numeric? What does your data in your table look like? This is unlikely to be the actual query you're running - if you need help with the true query, post it up
Oracle trim numeric values, you can fix it by adding ltrim to number:
select REGEXP_SUBSTR(ltrim(' 000.235')||'', '[^.]+', 1, 1) from dual;
result: 000 as expected

split a string on multiple delimiters

I have a sql that returns the example string below:
Input PKIND:BCMOX:10048301-
output BCMOX:10048301
I need to write code the first substring the string on - then split it on : and return the 2 & 3 item (BCMOX:10048301)
If the string format is consistent and you want to extract everything after the first : until the first occurrence of -, use a combination of substr and instr.
select substr(col, instr(col,':')+1, instr(col,'-')-instr(col,':')-1)
from yourtable
where instr(col,':') > 0 and instr(col,'-') > 0 --to get the rows which have these 2 characters
The REGEXP_SUBSTR version. Return everything between the first colon and the first hyphen.
select regexp_substr('PKIND:BCMOX:10048301-', ':(.*)-', 1, 1, NULL, 1) from dual;