Oracle regex replace issue - regex

I have one oracle table with one of the columns having below values,
,21A,22,21,28,28
I want to do a regex replace for removal of ,21 (The exact match) but it removes the value from ,21A
Below is my query,
update STUDENT set SCORES = REGEXP_REPLACE(SCORE, ',21' , '', 1, 1) where STUDENT_ID = 1;
How can this be achieved? Any ideas?

In your case, you can use a ,21(\W|$) regex. It matches ,21 that is followed with a non-word character or the end of string.
REGEXP_REPLACE(SCORE, ',21(\W|$)' , '\1', 1, 1)
Here is how you can perform a whole word search and replace in Oracle SQL:
regexp_replace(
haystack
, '(\W|^)(' || what_to_replace || ')(\W|$)'
, '\1' || with_what || '\3'
, 1
, 0
, 'imn'
)

Related

Regex_replace Postgres - Check if <= 2 characters length

I need 3 characters minimum for users accounts. I reuse existing names like
"tata-fzef - vcefv" or "kk" from the IMP_FR field to make this accounts.
In the second exemple, "kk" should become "k_k" because less than 3 characters.
How to do it with Postgresql?
regexp_replace( IMP_FR , regexp, first_character + '_' + last character, 'g')
Regular expressions won't help much here since REGEXP_REPLACE does not support conditional replacement patterns. You need different replacement pattern here for cases when the input only contains one, two or three or more chars.
So, it is better to rely on CASE ... WHEN ... ELSE here and the regular string manipulation functions:
CREATE TABLE tabl1
(s character varying)
;
INSERT INTO tabl1
(s)
VALUES
('tata-fzef - vcefv'),
('kkk'),
('kk'),
('k')
;
SELECT
CASE
WHEN LENGTH(s) = 1 THEN '_' || s || '_'
WHEN LENGTH(s) = 2 THEN LEFT(s,1) || '_' || RIGHT(s,1)
ELSE s
END AS Result
FROM tabl1;
See the online demo. Result:

Postgres regex to delimit multiple optional matches

Suppose a text field needs to be delimited in PostgreSQL. It is formatted as 'abcd' where each variable can be any one of: 1.4, 3, 5, 10, 15, 20 or N/A. Here is a query with some examples, followed by their expected results:
WITH example AS(
SELECT '10N/AN/AN/A' AS bw
UNION SELECT '1010N/AN/A'
UNION SELECT '101020N/A'
UNION SELECT '35N/A1.4'
UNION SELECT '1010N/A10'
UNION SELECT '105N/AN/A'
UNION SELECT '1.43N/A20'
)
SELECT
bw
,regexp_replace(
regexp_replace(
regexp_replace(
regexp_replace(
regexp_replace(
regexp_replace(
regexp_replace(bw, '(1\.4)', E'\\&|', 'g')
, '(3)', E'\\&|', 'g')
, '(5)', E'\\&|', 'g')
, '(10)', E'\\&|', 'g')
, '(15)', E'\\&|', 'g')
, '(20)', E'\\&|', 'g')
, '(N/A)', E'\\&|', 'g')
FROM
example
Results:
bw:text, regexp_replace:text
'1010N/AN/A', '10|10|N/A|N/A|'
'1010N/A10', '10|10|N/A|10|'
'35N/A1.4', '3|5|N/A|1.4|'
'1.43N/A20', '1.4|3|N/A|20|'
'105N/AN/A', '10|5|N/A|N/A|'
'101020N/A', '10|10|20|N/A|'
'10N/AN/AN/A','10|N/A|N/A|N/A|'
I'm not worried about the trailing pipe '|' since I can deal with it. This gets me what I want, but I'm concerned I could be doing it more succinctly. I experimented with putting each of the capture groups in a single regexp_replace statement while scouring through the documentation, but I was unable to get these results.
Can this be achieved within a single regexp_replace statement?
You may build a (1\.4|3|5|1[50]|20|N/A) capturing group with alternation operators separating the alternatives and replace with \1|:
select regexp_replace('35N/A1.4', '(1\.4|3|5|1[50]|20|N/A)', '\1|','g');
-- 35|N/A|1.4|
See the online demo
Details
( - starting the capturing group construct
1\.4 - 1.4 substring (. must be escaped in order to be parsed as a literal dot, else, it matches any char)
| - or
3 - a 3 char
| - or
5 - a 5 char
| - or
1[50] - 1 followed with either 5 or 0 (the [...] is called a bracket expression where you may specify chars, char ranges or even character classes)
| - or
20 - a 20 substring
| - or
N/A - a N/A substring
) - end of the capturing group.
The \1 in the replacement pattern is a numbered replacement backreference (also called a (group) placeholder) that references the value captured into Group 1.

How to split strings using two delimiter in Oracle 11g regexp_substr functions

I have doubt to split a string using the delimiter.
First split based on , delimiter select those splitted strings should split based on - delimiter
My original string: UMC12I-1234,CSM3-123,VQ,
Expected output:
UMC12I
CSM3
VQ
Each value comes as row value
I tried the option
WITH fab_sites AS (
SELECT trim(regexp_substr('UMC12I-1234,CSM3-123,VQ,', '[^,]+', 1, LEVEL)) fab_site
FROM dual
CONNECT BY LEVEL <= regexp_count('UMC12I-1234,CSM3-123,VQ,', '[^,]+')+1
)
SELECT fab_site FROM fab_sites WHERE fab_site IS NOT NULL
-- splitted based on , delimiter
Output is:
UMC12I-1234
CSM3-123
VQ
how can I get my expected output? (need to split again - delimiter)
You may extract the "words" before the - with the regexp_substr using
([^,-]+)(-[^,-]+)?
The pattern will match and capture into Group 1 one or more chars other than , and -, then will match an optional sequence of - and 1+ chars other than ,and -.
See the regex demo.
Use this regex_substr line instead of yours with the above regex:
SELECT trim(regexp_substr('UMC12I-1234,CSM3-123,VQ,', '([^,-]+)(-[^,-]+)?', 1, LEVEL, NULL, 1)) fab_site
See the online demo
You might try this query:
WITH fab_sites AS (
SELECT TRIM(',' FROM REGEXP_SUBSTR('UMC12I-1234,CSM3-123,VQ,', '(^|,)[^,-]+', 1, LEVEL)) fab_site
FROM dual
CONNECT BY LEVEL <= REGEXP_COUNT('UMC12I-1234,CSM3-123,VQ,', '(^|,)[^,-]+')
)
SELECT fab_site
FROM fab_sites;
We start by matching any substring that starts either with the start of the whole string ^ or with a comma ,, the delimiter. We then get all the characters that match neither a comma nor a dash -. Once we have that substring we trim any leftover commas from it.
P.S. I think the +1 in the CONNECT BY clause is extraneous, as is the WHERE NOT NULL in the "outer" query.

PL/SQL Regular Expression dash and brackets in the Matching Character List

My problem is that I need to remove all invalid characters from a column, but the dash and brackets characters are valid ones.
as so far my sql is:
SELECT REGEXP_REPLACE(column_name, '[^][-0-9a-z]' , '') FROM table_name;
but this doesn't include the dash character.
and:
SELECT REGEXP_REPLACE(column_name, '[^-][0-9a-z]' , '') FROM table_name;
this isn't good either.
There are 2 solutions for this:
1, use one of them at start and other at the end of the Matching Character List:
SELECT REGEXP_REPLACE(column_name, '[^][0-9a-z-]' , '') FROM table_name;
2, using the POSIX Collating Element Operator [.character.]:
SELECT REGEXP_REPLACE(column_name, '[^[.].][.[.][.-.]0-9a-z]' , '') FROM table_name;

Oracle Substring after specific character

I already found out I need to use substr/instr or regex but with reading the documentation about those, I cant get it done...
I am here on Oracle 11.2.
So here is what I have.
A list of Strings like:
743H5-34L-56
123HD34-7L
12HSS-34R
23Z67-4R-C23
What I need is the number (length 1 or 2) after the first '-' until there comes a 'L' or 'R'.
Has anybody some advice?
regexp_replace(string, '^.*?-(\d+)[LR].*$', '\1')
fiddle
Another version (without fancy lookarounds :-) :
with v_data as (
select '743H5-34L-56' val from dual
union all
select '123HD34-7L' val from dual
union all
select '12HSS-34R' val from dual
union all
select '23Z67-4R-C23' val from dual
)
select
val,
regexp_replace(val, '^[^-]+-(\d+)[LR].*', '\1')
from v_data
It matches
the beginning of the string "^"
one or more characters that are not a '-' "[^-]+"
followed by a '-' "-"
followed by one ore more digits (capturing them in a group) "(\d+)"
followed by 'L' or 'R' "[LR]"
followed by zero or more arbitrary characters ".*"