how to trim leading zero in oracle sql from concatenation text (text:number-number-number - oracle

how to trim leading zero in oracle sql from concatenation text
(text:number-number-number)
example(word:number-number-number) word can have text or double zero
but always has char before it after word, max digits separated by '-'
all time max 3 digits i want to keep zeros in first part. and after
that if remove leading 0 in sequence but keep it if it's only one 0
MachineAbc00:1-0-03 = MachineAbc00:1-0-3
MachineAbc00:1-001-02 = MachineAbc00:1-1-2
tried many combination, not successful , like
REGEXP_REPLACE ('MachineO00:1-0-03*', '0+(?!$)', '-')
REGEXP_REPLACE ('MTROPQFMO00:1-0-03*', '(-0){1,}', '-')

If all the input strings are in the exact format you said they are, then something like this should work:
with
sample_strings (str) as (
select 'MachineAbc00:1-0-03' from dual union all
select 'MachineAbc00:1-001-02' from dual union all
select 'MachineZzzyx:200-020-002' from dual union all
select 'machineCX032:0-000-0' from dual
)
select str as old_str,
regexp_replace(str, '([:-])0*(\d+)', '\1\2') as new_str
from sample_strings
;
OLD_STR NEW_STR
------------------------ ------------------------
MachineAbc00:1-0-03 MachineAbc00:1-0-3
MachineAbc00:1-001-02 MachineAbc00:1-1-2
MachineZzzyx:200-020-002 MachineZzzyx:200-20-2
machineCX032:0-000-0 machineCX032:0-0-0
The regular expression function finds any occurrence of (colon or dash) followed by (zero or more 0 characters/digits) followed by at least one more digit. The "zero or more 0 digits" is maximal with the property that there must be at least one more digit AFTER that match (even if that extra digit hapens to be a zero - see my last test string, which I added precisely in order to test that this works correctly). The function replaces each such occurrence with the first and third fragments, removing the middle one (the zeros you must remove from your string). The references \1 and \2 refer to the first and the second parenthesized sub-expressions - the punctuation mark (colon or dash) and, respectively, the final digits (excluding the leading zeros that must be removed).

Related

Oracle query to find any special character in first position or end position of the field value

I have a table in Oracle database with special characters attached at first and last position in the field value. I want to eliminate those special characters while querying the table. I have used INSTR function but I had to apply for each and every special character using CASE expression.
Is there a way to eliminate any special characters that is attached only at first and last positions in one shot?
The query I am using as is below:
CASE WHEN
INSTR(emp_address,'"')=1 THEN REPLACE((emp_address,'"', '').
.
.
.
You can use regular expressions to replace the leading and trailing character of a string if they match the regular expression pattern. For example, if your definition of a "special character" is anything that is not an alpha-numeric character then you can use the regular expression:
^ the start-of-the-string then
[^[:alnum:]] any single character that does not match the POSIX alpha-numeric character group
| or
[^[:alnum:]] any single character that does not match the POSIX alpha-numeric character group then
$ the end-of-the-string.
Like this:
SELECT emp_address,
REGEXP_REPLACE(
emp_address,
'^[^[:alnum:]]|[^[:alnum:]]$'
) AS simplified_emp_address
FROM table_name
Which, for the sample data:
CREATE TABLE table_name (emp_address) AS
SELECT 'test' FROM DUAL UNION ALL
SELECT '"test2"' FROM DUAL UNION ALL
SELECT 'Not "this" one' FROM DUAL;
Outputs:
EMP_ADDRESS
SIMPLIFIED_EMP_ADDRESS
test
test
"test2"
test2
Not "this" one
Not "this" one
If you have a more complicated definition of a special character then change the regular expression appropriately.
db<>fiddle here

FInd if the fifth position is a letter and not a number using ORACLE

How can I find if the fifth position is a letter and thus not a number using Oracle ?
My last try was using the following statement:
REGEXP_LIKE (table_column, '([abcdefghijklmnopqrstuvxyz])');
Perhaps you'd rather check whether 5th position contains a number (which means that it is not something else), i.e. do the opposite of what you're doing now.
Why? Because a "letter" isn't only ASCII; have a look at the 4th row in my example - it contains Croatian characters and these aren't between [a-z] (nor [A-Z]).
SQL> with test (col) as
2 (select 'abc_3def' from dual union all
3 select 'A435D887' from dual union all
4 select '!#$%&/()' from dual union all
5 select 'ASDĐŠŽĆČ' from dual
6 )
7 select col,
8 case when regexp_like(substr(col, 5, 1), '\d+') then 'number'
9 else 'not a number'
10 end result
11 from test;
COL RESULT
------------- ------------
abc_3def number
A435D887 not a number
!#$%&/() not a number
ASDĐŠŽĆČ not a number
SQL>
Anchor to the start of the string else you may get unexpected results. This works, but remove the caret (start of string anchor) and it returns 'TRUE'! Note it uses the case-insensitive flag of 'i'.
select 'TRUE'
from dual
where regexp_like('abcd4fg', '^.{4}[A-Z]', 'i');
Yet another way to do it:
regexp_like(table_column, '^....[[:alpha:]]')
Using the character class [[:alpha:]] will pick up all letters upper case, lower case, accented and etc. but will ignore numbers, punctuation and white space characters.
If what you care about is that the character is not a number, then use
not regexp_like(table_column, '^....[[:digit:]]')
or
not regexp_like(table_column, '^....\d')
Try:
REGEXP_LIKE (table_column, '^....[a-z]')
Or:
SUBSTR (table_column, 5, 1 ) BETWEEN 'a' AND 'z'

Oracle joining tables where the matching process starts after certain digits

I have joined two tables which contain words as well as values. The matching of the words works. The matching of the values do not. The reason is that the values in the table "GATTUNGSDATEN" always start with 4 zeros whereas in the table BONDMAPPING not. E.g. 00001234 = 1234. What query could I use in order to have the matching process started after 4 digits?
select MET_SEC_INDEX_GATTUNGSDATEN.ranl, MET_SEC_INDEX_GATTUNGSDATEN.vvranlwx,
V_AR_BONDMAPPING.MUREXEXTERNALID
from V_AR_BONDMAPPING
RIGHT JOIN MET_SEC_INDEX_GATTUNGSDATEN
ON V_AR_BONDMAPPING.MUREXEXTERNALID = MET_SEC_INDEX_GATTUNGSDATEN.ranl IN
('%%%%')
where vvranlwi=34
If it's always four leading zeroes you can use SUBSTR():
from V_AR_BONDMAPPING
RIGHT JOIN MET_SEC_INDEX_GATTUNGSDATEN
ON V_AR_BONDMAPPING.MUREXEXTERNALID = substr(MET_SEC_INDEX_GATTUNGSDATEN.ranl, 5)
This trims the leading four characters from MET_SEC_INDEX_GATTUNGSDATEN.ranl
If you know the length of the identifiers you could pad the shorter identifier with leading zeroes
select lpad(1234, 8, '0') from dual
=>
00001234
select lpad('00001234', 8, '0') from dual
=>
00001234
This will implicitly convert the numbers into VARCHAR2s however, which on the other hand is what would happen anyways during the comparison

How Can I Extract String in Oracle

I would like to extract following string in Oracle. How can I do that?
Original String: 011113584378(+) CARD, STAFF
Expected String: STAFF CARD
I presume you have the luxury of writing a PL/SQL function? Then just use "SUBSTR", and/or "INSTR", and || concatenation operator to parse your input.
Here is an example:
https://www.techonthenet.com/oracle/questions/parse.php
...The field may contain the following value:
F:\Siebfile\YD\S_SR_ATT_1-60SS_1-AM3L.SAF
In this case, I need to return the value of '1-60SS', as this is the value that resides between the 3rd and 4th underscores.
SOLUTION:
create or replace function parse_value (pValue varchar2)
return varchar2
is
v_pos3 number;
v_pos4 number;
begin
/* Return 3rd occurrence of '_' */
v_pos3 := INSTR (pValue, '_', 1, 3) + 1;
/* Return 4rd occurrence of '_' */
v_pos4 := INSTR (pValue, '_', 1, 4);
return SUBSTR (pValue, v_pos3, v_pos4 - v_pos3);
end parse_value;
Ok, I'll bite. This example uses REGEXP_REPLACE to describe the string, saving the parts you need in order to rearrange them before returning them. It would be better if you showed some real-world examples of the data you are dealing with as I can only guarantee this example will work with the one line you provided.
The regular expression matches any characters starting at the beginning of the string and ending with a close paren-space. The next set of any characters up to but not including the comma-space is "remembered" by enclosing them in parens. This is called a captured group. The next captured group is the set of characters after that comma-space separator until the end of the line (the dollar sign). The captured groups are referred to by their order from left to right. The 3rd argument is the string to return, which is the 2nd and 1st captured groups, in that order, separated by a space.
SQL> with tbl(str) as (
select '+011113584378(+) CARD, STAFF' from dual
)
select regexp_replace(str, '^.*\) (.*), (.*)$', '\2 \1') formatted
from tbl;
FORMATTED
----------
STAFF CARD
SQL>

Retrieving first X words from a string in Oracle Select

I need to select the first X words in a string, where x can be any number from 0-100. Is there an easy way to do this? I found the following example to select the first 2 words from a string:
select regexp_replace('Hello world this is a test', '(\w+ \w+).*$','\1') as first_two
from dual
How would I select the first X words from a string where X can be a number from 0-100?
Selecting the first four words:
select
regexp_replace(
'Hello world this is a test etc',
'(((\w+)\s){4}).*', -- Change 4 to wanted number of words here!
'\1'
)
from dual;
Edit
The above solution only works if the words are seperated by exactly one white space character. If the words are seperated by one or more white space characters, the \s must be extended to \s+:
select
regexp_replace(
'Hello world this is a test etc',
'(((\w+)\s+){4}).*', -- Change 4 to wanted number of words here!
'\1'
)
from dual;
This method takes the result of extracting the number of words you want, then reduces multiple spaces to one:
select trim(regexp_replace(regexp_substr('Hello world this is a test etc', '(([^ ]*)( |$)*){3}'), ' +', ' '))
from dual;
EDIT: This is getting ugly, but wrapped a TRIM() around it to get rid of the trailing space (the one after the last word selected).
this would do it, but it may be a bit inelegant, replace "2" with the number of words to find
select substr('this is a number of words',1,instr('this is a number of words',' ',1,2))
from dual
does assume words always end with a space

Resources