Replace a specific character in a string - oracle

How can I replace the 12th character of a string if it's equal to 'X'
For example if I have 'ABXD1X354XJXOKJX'; in this case I will replace the 'X' in the 12th position with 'Y'. result : 'ABXD1X354XJYOKJX'
I was thinking to use regexp_replace function to point the 12th character, test if it's equal to 'X', if yes replace it with 'Y' but it's more complicated than I thought

This should work for you using SUBSTR:
select
substr('ABXD1X354XJXOKJX', 1, 11) ||
case when substr('ABXD1X354XJXOKJX', 12, 1) = 'X' THEN 'Y' ELSE substr('ABXD1X354XJXOKJX', 12, 1) END ||
substr('ABXD1X354XJXOKJX', 13)
from dual
SQL Fiddle Demo

without knowing more of how are constituted your string, this should work:
-- matches:
select regexp_replace('12dasdf32432Xasdasd', '([[:alnum:]]{11})(X{1})', '\1Y' ) from dual
union
-- doesn't match:
select regexp_replace('12dasdf32432Zasdasd', '([[:alnum:]]{11})(X{1})', '\1Y' ) from dual

you can do:
CASE SUBSTR(yourfield, 12, 1) WHEN 'X' THEN 'Y' END
and add in concatenation as necessary

For this, it may be just as easy to use the SUBSTR function.
Example, if UPPER(SUBSTR('ABXD1X354XJYOKJX', 12, 1)) = 'X'

Related

How to extract a value inside column in certain pattern in oracle

I want to extract data in the format (465797,461396) from (',7809628#465797,7809628#461396,') data. How can I do that?
[DBFiddle][1]
select
ltrim(
regexp_replace(
',7809628#465797,7809628#461396,'
,'[^#]*#(\d+),'
,',\1')
,','
) new_str
from dual;
Results:
NEW_STR
-------------
465797,461396
Regexp '[^#]*#(\d+),':
[^#]* - any number of any symbols except '#'
(\d+) - digits, one or more digits, () - marks it as a group
and comma after that.
So it finds (any symbols except #, then #, then one or more digits, then comma) and replaces all found substrings to comma and found "one or more digits"(the only group in the expression). Then ltrim removes extra comma in the beggining.
[1]: https://dbfiddle.uk/?rdbms=oracle_11.2&fiddle=f66505cd2746a1387e41ec91d6c7df3a
You can use simple string functions (which may be more to type than with a regular expression but is likely to execute quicker):
SELECT SUBSTR(value, hash1 + 1, comma2 - hash1 - 1)
|| ',' ||
SUBSTR(value, hash2 + 1, comma3 - hash2 - 1) AS parsed_value
FROM (
SELECT value,
INSTR(value, '#', 1, 1) AS hash1,
INSTR(value, '#', 1, 2) AS hash2,
INSTR(value, ',', 1, 2) AS comma2,
INSTR(value, ',', 1, 3) AS comma3
FROM table_name
)
Which, for the sample data:
CREATE TABLE table_name (value) AS
SELECT ',7809628#465797,7809628#461396,' FROM DUAL;
Outputs:
PARSED_VALUE
465797,461396
db<>fiddle here

How to append parenthesis if a specific condition satisfies in Oracle

I have below query which gives me output like -$97.90 or $11.00
Select TRIM(to_char(pen_amt,'$999,999,999,999,999.99')) as PenAmount
from transact;
Now, if the value starts with -, I want to remove - and encapsulate the same as ($97.90). How can I do this?
Also using the PR format model element, which surrounds positive (and zero) values with single spaces and negative numbers with angled brackets: You can follow that up with the TRANSLATE function if you really need the format you requested. (Notice that if I use TRANSLATE, I don't need to use TRIM, or the format model modifier FM in TO_CHAR, which would do the same thing; I can simply remove the spaces with TRANSLATE.)
with
test_data (amount) as (
select 320.88 from dual union all
select -309 from dual
)
select amount,
to_char(amount, '$999,999,999.99pr') as pr_formatted_amount,
translate(to_char(amount, '$999,999,999.99pr'), '<> ', '()')
as my_formatted_amount
from test_data
;
AMOUNT PR_FORMATTED_AMOUNT MY_FORMATTED_AMOUNT
---------- ------------------- -------------------
320.88 $320.88 $320.88
-309 <$309.00> ($309.00)
If you can use <> brackets then PR will do the trick.
Select TRIM(to_char(pen_amt,'$999,999,999,999,999.99PR')) as PenAmount from transact;
Use a CASE statement to check if the value starts with -:
Select
case when TRIM(to_char(pen_amt,'$999,999,999,999,999.99')) like '-%'
then '(' || substr(TRIM(to_char(pen_amt,'$999,999,999,999,999.99')), 2) || ')'
else TRIM(to_char(pen_amt,'$999,999,999,999,999.99'))
end as PenAmount
from transact;
Or by directly checking if pen_amt is negative:
Select
case when pen_amt < 0
then '(' || TRIM(to_char(abs(pen_amt),'$999,999,999,999,999.99')) || ')'
else TRIM(to_char(pen_amt,'$999,999,999,999,999.99'))
end as PenAmount
from transact;
Use a combination of PR in the mask along with TRANSLATE to convert angle brackets to parentheses.
Select translate(to_char(-12345.6789,'FM$999,999,999,999,999.99PR'),'<>','()') as PenAmount from dual;
Select translate(to_char(23456.789,'FM$999,999,999,999,999.99PR'),'<>','()') as PenAmount from dual;
($12,345.68)
$23,456.79
The PR mask puts angle brackets for negative numbers.
The FM mask tells Oracle to show the minimal text (i.e. TRIM it).

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'

How to apply regular expression on the below given string

i have a string 'MCDONALD_YYYYMMDD.TXT' i need to use regular expressions and append the '**' after the letter 'D' in the string given . (i.e In the string at postion 9 i need to append '*' based on a column value 'star_len'
if the star_len = 2 the o/p = ''MCDONALD??_YYYYMMDD.TXT'
if the star_len = 1 the o/p = ''MCDONALD?_YYYYMMDD.TXT'
with
inputs ( filename, position, symbol, len ) as (
select 'MCDONALD_20170812.TXT', 9, '*', 2 from dual
)
-- End of simulated inputs (for testing purposes only, not part of the solution).
-- SQL query begins BELOW THIS LINE.
select substr(filename, 1, position - 1) || rpad(symbol, len, symbol)
|| substr(filename, position) as new_str
from inputs
;
NEW_STR
-----------------------
MCDONALD**_20170812.TXT
select regexp_replace('MCDONALD_YYYYMMDD.TXT','MCDONALD','MCDONALD' ||
decode(star_len,1,'*',2,'**'))
from dual
This is how you could do it. I don't think you need it as a regular expression though if it is always going to be "MCDONALD".
EDIT: If you need to be providing the position in the string as well, I think a regular old substring should work.
select substr('MCDONALD_YYYYMMDD.TXT',1,position-1) ||
decode(star_len,1,'*',2,'**') || substr('MCDONALD_YYYYMMDD.TXT',position)
from dual
Where position and star_len are both columns in some table you provide(instead of dual).
EDIT2: Just to be more clear, here is another example using a with clause so that it runs without adding a table in.
with testing as
(select 'MCDONALD_YYYYMMDD.TXT' filename,
9 positionnum,
2 star_len
from dual)
select substr(filename,1,positionnum-1) ||
decode(star_len,1,'*',2,'**') ||
substr(filename,positionnum)
from testing
For the fun of it, here's a regex_replace solution. I went with a star since that what your variable was called even though your example used a question mark. The regex captures the filename string in 2 parts, the first being from the start up to 1 character before the position value, the second the rest of the string. The replace puts the captured parts back together with the stars in between.
with tbl(filename, position, star_len ) as (
select 'MCDONALD_20170812.TXT', 9, 2 from dual
)
select regexp_replace(filename,
'^(.{'||(position-1)||'})(.*)$', '\1'||rpad('*', star_len, '*')||'\2') as fixed
from tbl;

String Manipulation in Oracle 11g

I am currently working on an exercise that will display a certain text, say TESTTEMP, from a series of characters stored in a column. Example of the string:
PROGRAMNAME|MAX2112ETI_L;PROGRAMREV|L;TESTOPTION|FR;TESTTEMP|25;STD IPH|528.63436123348
Now what I need is to extract the text past the string TESTTEMP| and before the ;. What I did is I extracted all the text past TESTTEMP| and just get the first two character. Unfortunately, this will not be possible since there are cases where in the TESTTEMP| has 3 characters. Is there a way for me to be able to do this? Below is what I have so far:
SELECT
SUBSTR(SUBSTR(value, INSTR(value, ';TESTTEMP|')+10), 1, 2) invalue
FROM
(
SELECT
'PROGRAMNAME|MAX2112ETI_L;PROGRAMREV|L;TESTOPTION|FR;TESTTEMP|25;STD IPH|528.63436123348' VALUE
FROM dual
)t;
Find the index of ; in the substring and use that as index instead of hard coding it to 2.
SELECT
SUBSTR(SUBSTR(value, INSTR(value, ';TESTTEMP|')+10), 1, INSTR(SUBSTR(value, INSTR(value, ';TESTTEMP|')+10), ';')-1) invalue
FROM
(
SELECT
'PROGRAMNAME|MAX2112ETI_L;PROGRAMREV|L;TESTOPTION|FR;TESTTEMP|25;STD IPH|528.63436123348' VALUE
FROM dual
)t;
If that look messy, you can even write it like this
SELECT
SUBSTR(VALUE, 1, INSTR(VALUE, ';') - 1) invalue
FROM
(
SELECT
SUBSTR(VALUE, INSTR(VALUE, ';TESTTEMP|') + 10)
VALUE
FROM (
SELECT
'PROGRAMNAME|MAX2112ETI_L;PROGRAMREV|L;TESTOPTION|FR;TESTTEMP|25;STD IPH|528.63436123348'
VALUE
FROM dual) t
)t;
Based on comments - if you want to know if the string was found or not, use this query. FOUND will be greater than 0 if the string is found.
SELECT
SUBSTR(VALUE, 1, INSTR(VALUE, ';')-1) invalue, FOUND
FROM
(
SELECT
SUBSTR(VALUE, INSTR(VALUE, SEARCHSTRING)+10) VALUE, INSTR(VALUE, SEARCHSTRING) FOUND
FROM (
SELECT
'PROGRAMNAME|MAX2112ETI_L;PROGRAMREV|L;TESTOPTION|FR;TESTTEMP|25;STD IPH|528.63436123348'
VALUE,
';TESTTEMP|' SEARCHSTRING
FROM dual) t
)t;

Resources