Oracle SQL - select parts of a string - sql

How can I select abcdef.txt from the following string?
abcdef.123.txt
I only know how to select abcdef by doing select substr('abcdef.123.txt',1,6) from dual;

You can using || for concat and substr -3 for right part
select substr('abcdef.123.txt',1,6) || '.' ||substr('abcdef.123.txt',-3) from dual;
or avoiding a concat (like suggested by Luc M)
select substr('abcdef.123.txt',1,7) || substr('abcdef.123.txt',-3) from dual;

A general solution, assuming the input string has exactly two periods . and you want to extract the first and third tokens, separated by one . The length of the "tokens" in the input string can be arbitrary (including zero!) and they can contain any characters other than .
select regexp_replace('abcde.123.xyz', '([^.]*).([^.]*).([^.]*)', '\1.\3') as result
from dual;
RESULT
---------
abcde.xyz
Explanation:
[ ] means match any of the characters between brackets.
^
means do NOT match the characters in the brackets - so...
[^.]
means match any character OTHER THAN .
* means match zero or
more occurrences, as many as possible ("greedy" match)
( ... ) is called a subexpression... see below
'\1.\3 means replace the original string
with the first subexpression, followed by ., followed by the THIRD
subexpression.

Replace the substring of anything surrounded by dots (inclusive) with a single dot. No dependence on lengths of components of the string:
SQL> select regexp_replace('abcdef.123.txt', '\..*\.', '.') fixed
from dual;
FIXED
----------
abcdef.txt
SQL>

Related

fixed number format with different lengths in Oracle

I need help with a Oracle Query
I have a query:
scenario 1: select to_char('1737388250',what format???) from dual;
expected output: 173,7388250
scenario 2: select to_char('173738825034',what format??) from dual;
expected output: 173,738825034
scenario 3: select to_char('17373882',what format??) from dual;
expected output: 173,73882
I need a query to satify all above scenarios?
Can some one help please?
It is possible to get the desired result with a customized format model given to to_char; I show one example below. However, any solution along these lines is just a hack (a solution that should work correctly in all cases, but using features of the language in ways they weren't intended to be used).
Here is one example - this will work if your "inputs" are positive integers greater than 999 (that is: at least four digits).
with
sample_data (num) as (
select 1737388250 from dual union all
select 12338 from dual
)
select num, to_char(num, rpad('fm999G', length(num) + 3, '9')) as formatted
from sample_data
;
NUM FORMATTED
---------- ------------
1737388250 173,7388250
12338 123,38
This assumes comma is the "group separator" in nls_numeric_characters; if it isn't, that can be controlled with the third argument to to_char. Note that the format modifier fm is needed so that no space is prepended to the resulting string; and the +3 in the second argument to rpad accounts for the extra characters in the format model (f, m and G).
You can try
select TO_CHAR(1737388250, '999,99999999999') from dual;
Take a look here
Your requirement is different so you can use substr and concatanation as follows:
select substr(your_number,1,3)
|| case when your_number >= 1000 then ',' end
|| substr(1737388250,4)
from dual;
Db<>fiddle
Your "number" is enclosed in single-quotes. This makes it a character string, albeit a string of only numeric characters. But a character string, nonetheless. So it makes no sense to pass a character string to TO_CHAR.
Everyone's suggestions are eliding over this and useing and using an actual number .. notice the lack of single-quotes in their code.
You say you always want a comma after the first three "numbers" (characters), which makes no sense from a numerical/mathematical sense. So just use INSTR and insert the comma:
select substr('123456789',1,3)||','||substr('123456789',4) from dual:
If the source data is actually a number, then pass it to to_char, and wrap that in substr:
select substr(to_char(123456789),1,3)||','||substr(to_char(123456789,4) from dual:

SQL Query to select a string after last delimiter

I want to retrieve a String after last appearance of ~ delimiter. I have whole string like "Attachments:Attachments~Attachment" and I want to take substring after ~ characters that is output will be Attachment. How can be this done in SQL/Oracle select statement?
Use REGEXP_SUBSTR
select regexp_substr('Attachments:Attachments~Attachment','[^~]+$') from dual;
[^ ] - Used to specify a nonmatching list where you are trying to match any character except for the ones in the list.
+ - Matches one or more occurrences
$ - Matches the end of a string
Demo on db<>fiddle
You can use the substr and instr for such simple pattern matching requirements as regexp will be costly compared to substr and instr combination.
You can try the following:
substr(str,instr(str,'~',-1) + 1)
Example:
SQL> select substr('Attachments:Attachments~Attachment1~Attachment2',
2 instr('Attachments:Attachments~Attachment1~Attachment2','~',-1) + 1)
3 from dual;
SUBSTR('ATT
-----------
Attachment2
SQL>

Extract character between the first two characters

I have a table in BigQuery:
ab_col_jfsfhfd_ggg_sdf
arfd_am_fdsf_fddg_fg
d_fdf_fdddg_ffddd_f
I would like to extract those characters that go right after the first _ character and followed by the second _ character. I want to get the following:
col
am
fdf
I used the following regular expression to extract the characters but it does not work as intended:
^.*\_(\D+)\_.*$
regexp_replace(id,'^.*\\_(\\D+)\\_.*$' , '\\1')
Please help!
If I follow you correctly, you can use split():
(split(col, '_'))[safe_ordinal(2)]
split() turns the string column to an array of values, given a separator (here, we use _). Then we can just grab second array element.
split() is a very simply way of solving this. But regular expressions are also quite simple:
with t as (
select 'ab_col_jfsfhfd_ggg_sdf' as id union all
select 'arfd_am_fdsf_fddg_fg' union all
select 'd_fdf_fdddg_ffddd_f'
)
select id, regexp_extract(id, '[^_]+', 1, 2)
from t;
The logic for the pattern is: "Look for any string of characters that is not an underscore. Then take the second one in the string."
Use regexp_extract:
regexp_extract(id,'^[^_]+_([^_]+)')
See proof
Explanation
--------------------------------------------------------------------------------
^ the beginning of the string
--------------------------------------------------------------------------------
[^_]+ any character except: '_' (1 or more times
(matching the most amount possible))
--------------------------------------------------------------------------------
_ '_'
--------------------------------------------------------------------------------
( group and capture to \1:
--------------------------------------------------------------------------------
[^_]+ any character except: '_' (1 or more
times (matching the most amount
possible))
--------------------------------------------------------------------------------
) end of \1

Extract Specific Set of data from a String in Oracle

I have the string '1_A_B_C_D_E_1_2_3_4_5' and I am trying to extract the data 'A_B_C_D_E'. I am trying to remove the _1_2_3_4_5 & the 1_ portion from the string. Which is essentially the numeric portion in the string. any special characters after the last alphabet must also be removed. In this example the _ after the character E must also not be present.
and the Query I am trying is as below
SELECT
REGEXP_SUBSTR('1_A_B_C_D_E_1_2_3_4_5','[^0-9]+',1,1)
from dual
The Data I get from the above query is as below: -
_A_B_C_D_E_
I am trying to figure a way to remove the underscore towards the end. Any other way to approach this?
Assuming the "letters" come first and then the "digits", you could do something like this:
select regexp_substr('A_B_C_D_E_1_2_3_4_5','.*[A-Z]') from dual;
This will pull all the characters from the beginning of the string, up to the last upper-case letter in the string (.* is greedy, it will extend as far as possible while still allowing for one more upper-case letter to complete the match).
I have the string '1_A_B_C_D_E_1_2_3_4_5' and I am trying to extract the data 'A_B_C_D_E'
Use REGEXP_REPLACE:
SQL> SELECT trim(BOTH '_' FROM
2 (REGEXP_SUBSTR('1_A_B_C_D_E_1_2_3_4_5','[0-9]+', ''))) str
3 FROM dual;
STR
---------
A_B_C_D_E
How it works:
REGEXP_REPLACE will replace all numeric occurrences '[0-9]+' from the string. Alternatively, you could also use POSIX character class '[^[:digit:]]+'
TRIM BOTH '_' will remove any leading and lagging _ from the string.
Also using REGEXP_SUBSTR:
SELECT trim(BOTH '_' FROM
(REGEXP_SUBSTR('1_A_B_C_D_E_1_2_3_4_5','[^0-9]+'))) str
FROM dual;
STR
---------
A_B_C_D_E

Oracle: How to use regexp_substr in this case

I have a table in Oracle where one of the column contains UserIds which are in the form of \. For eg "fin\george", "sales\andy" etc. How can I use REGEXP_SUBSTR function to get only the from the UserIds. ie I want to fetch only "george", "andy" etc. I have achieved the desired reult using SUBSTR function but I want to use REGEXP_SUBSTR in this case.
I tried doing this:
SELECT REGEXP_SUBSTR('fin\george','\[^\]+,') "UserName" FROM DUAL;
but it did'nt help. Can anyone please point out my mistake ?
I believe you want to use a regexp_replace with a backreference. I'm assuming that all the characters before and after the \ are alphabetic. If you allow numbers, you'd want to use the [[:alnum:]] rather than [[:alpha::].
1* SELECT REGEXP_replace('fin\george',
'([[:alpha:]]+\\)([[:alpha:]]+)$',
'\2') "UserName"
FROM DUAL
SQL> /
UserNa
------
george
SQL> SELECT REGEXP_SUBSTR('fin\george', '[^\]+', 1, 2) AS userId from dual;
USERID
------
george
See this Oracle Base article
select regexp_replace( 'fin\george', '.*\\', null ) from dual;
returns george.
The regex will match any character followed by the \ (which is escaped), as many times as possible (greedy).
So it will match everything up to the final \.
Then the matching string is replaced with null.
null is the default so
select regexp_replace('fin\george', '.*\\' ) from dual;
does the same thing
Same expression can extract filename from the end of pathname e.g.
select regexp_replace ('fin\fin2\fin3\fin4\george', '.*\\' ) from dual;
will also return george.
You have to use escaping: \\ instead of \
The easiest way (IMHO) to do this is the following:
SELECT REGEXP_SUBSTR('fin\george', '[^\\]+$') AS "UserName" FROM DUAL;
The issues with your original query were (a) that the \ character was not escaped and (b) there was an extraneous comma in the regular expression. I've used the end-of-string anchor $ here, assuming that there are not more than two elements delimited by \. If there are more than two, and you need only the second one, you can use the following:
SELECT REGEXP_SUBSTR('fin\george\ringo', '[^\\]+', 1, 2) AS "UserName"
FROM DUAL;
This tells Oracle to start looking at the first character of the string and return the second match.