We need to mask data for the String up to fixed length in Oracle - sql

I am trying to mask the data for the below String :
This is the new ADHAR NUMBER 123456789989 this is the string 3456798983 from Customer Name like 345678 to a String .
In above data I want to mask data starting from ADHAR NUMBER to length up to 60 characters.
OUTPUT :
This is the new *********************************************************Customer Name like 345678 to a String .
Can anyone please help

A little bit of substr + instr does the job (sample data in the first 2 lines; query begins at line #3):
SQL> with test (col) as
2 (select 'This is the new ADHAR NUMBER 123456789989 this is the string 3456798983 from Customer Name like 345678 to a String .' from dual)
3 select substr(col, 1, instr(col, 'ADHAR NUMBER') - 1) ||
4 lpad('*', 60, '*') ||
5 substr(col, instr(col, 'ADHAR NUMBER') + 60) result
6 from test;
RESULT
--------------------------------------------------------------------------------
This is the new ************************************************************ Cus
tomer Name like 345678 to a String .
SQL>

Here is a solution that covers all possibilities (I think). Notice the different inputs in the WITH clause (which is not part of the solution - remove it, and use your actual table and column names in the query). This is how one should test their solutions - consider all possible cases, including NULL input, non-NULL input string that doesn't contain the "magic words", string that has the "magic words" right at the beginning, etc.
There is one important situation the solution does NOT address, namely when the exact substring 'ADHAR NUMBER' is not two full words, but it is part of longer words - for example 'BHADHAR NUMBERS'. In this case the output will look like 'BH****************' masking ADHAR NUMBER and the S after NUMBER and more characters, up to 60 total.
Note that the output string has the same length as the input. This is generally part of the definition of "masking".
with
test (col) as (
select 'This is the new ADHAR NUMBER 123456789989 this is the string ' ||
'3456798983 from Customer Name like 345678 to a String.'
from dual union all
select 'This string does not contain the magic words' from dual union all
select 'ADHAR NUMBER 12345' from dual union all
select 'Blah blah ADHAR NUMBER 1234' from dual union all
select null from dual union all
select 'Another blah ADHAR NUMBER' from dual
)
select case when pos > 0
then
substr(col, 1, pos - 1) ||
rpad('*', least(60, length(col) - pos + 1), '*') ||
substr(col, pos + 60)
else col end as masked
from (
select col, instr(col, 'ADHAR NUMBER') as pos
from test
)
;
MASKED
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
This is the new ************************************************************ Customer Name like 345678 to a String.
This string does not contain the magic words
******************
Blah blah *****************
Another blah ************

Related

Oracle replace all characters before "." dot

I need to replace all characters with nothing before the . character and also replace all [ and ] with nothing.
Please see examples below:
from
to
[PINWHEEL_ASSET].[MX5530]
MX5530
[PINWHEEL_TRADE].[AR5403]
AR5403
The parts before and after the . dot are variables.
with
sample_data (my_string) as (
select '[PINWHEEL_ASSET].[MX5530]' from dual
)
select rtrim(substr(my_string, instr(my_string, '.') + 2), ']') as second_part
from sample_data
;
SECOND_PART
-----------
MX5530
This assumes that the input string looks exactly like this: [first].[second], where "first" and "second" are (possibly empty) strings that do not contain periods or closing brackets.
Yet another option is to use regular expressions (see line #6).
Sample data:
SQL> with test (col) as
2 (select '[PINWHEEL_ASSET].[MX5530]' from dual union all
3 select '[PINWHEEL_TRADE].[AR5403]' from dual
4 )
Query begins here:
5 select col,
6 regexp_substr(col, '\w+', 1, 2) result
7 from test;
COL RESULT
------------------------- --------------------
[PINWHEEL_ASSET].[MX5530] MX5530
[PINWHEEL_TRADE].[AR5403] AR5403
SQL>

Remove 2 characters in oracle sql

I have a column that contains 12 digits but user wants only to generate a 10 digits.
I tried the trim, ltrim function but nothing work. Below are the queries I tried.
ltrim('10', 'column_name')
ltrim('10', column_name)
ltrim(10, column_name)
For example I have a column that contains a 12 digit number
100000000123
100000000456
100000000789
and the expected result I want is
0000000123
0000000456
0000000789
To extract the last 10 characters of an input string, regardless of how long the string is (so this will work if some inputs have 10 characters, some 12, and some 15 characters), you could use negative starting position in substr:
substr(column_name, -10)
For example:
with
my_table(column_name) as (
select '0123401234' from dual union all
select '0001112223334' from dual union all
select '12345' from dual union all
select '012345012345' from dual
)
select column_name, substr(column_name, -10) as substr
from my_table;
COLUMN_NAME SUBSTR
------------- ----------
0123401234 0123401234
0001112223334 1112223334
12345
012345012345 2345012345
Note in particular the third example. The input has only 5 digits, so obviously you can't get a 10 digit number from it. The result is NULL (undefined).
Note also that if you use something like substr(column_name, 3) you will get just '345' in that case; most likely not the desired result.
try to use SUBSTR(column_name, 2)

how to split a string with special characters in oracle pl/sql

I want to split the below string based on certain string. How can we do this?
abc\\10.2.4\\string with spaces\\1.2.3-another-string\\def\\string_with_underscores
split by 'def'
You can use regexp_replace as in the following query :
with tab(str) as
(
select 'abc\\10.2.4\\string with spaces\\1.2.3-another-string\\def\\string_with_underscores'
from dual
)
select regexp_replace(str,'def.*','') str1,
regexp_replace(str,'.*def','') str2
from tab;
STR1 STR2
------------------------------------------------------- -------------------------
abc\\10.2.4\\string with spaces\\1.2.3-another-string\\ \\string_with_underscores
Would this do any good?
SQL> with test (col) as
2 (select 'abc\\10.2.4\\string with spaces\\1.2.3-another-string\\def\\string_with_underscores' from dual)
3 select regexp_substr(replace(col, 'def', '#'), '[^#)]+', 1, level) res
4 from test
5 connect by level <= regexp_count(col, 'def') + 1;
RES
--------------------------------------------------------------------------------
abc\\10.2.4\\string with spaces\\1.2.3-another-string\\
\\string_with_underscores
SQL>
lines 1 and 2 represent your data
lines 3 - 5 are used to split that column into rows
line 3: REPLACE replaces 'def' with '#' which becomes a new delimiter
line 5: you'll have as many rows as there are 'def' delimiters in a string + 1 (i.e. if there are 4 'def' delimiters, you'll have 5 rows as a result)
This option doesn't require you to know in advance how many substrings you'll get as a result, it is dynamic.

How to extract e-mail from string

I'd like to extract e-mail from string.
I have the string abc defg email#email.com and I would like to get the string email#email.com.
How could I do it in PL / SQL?
Something like this will work for many situations, but is far from perfect. I added one string that demonstrates two different ways in which this may fail, you will notice them. It will not be easy to write a query that catches ALL possible situations; how far you take the further refinement of the "match pattern" depends on how out-of-the-ordinary the emails in your input data may be.
In the regular expression, note that the dot (.) must be escaped with a backslash, and within matching lists (lists of characters in square brackets) the hyphen - must be either the first or the last characters in the list, anywhere else it is a metacharacter.
In the output, notice the last row; the input string is empty, so the output is null as well.
with
input_strings ( str ) as (
select 'sdss abc#gmail.com sdsda sdsds ' from dual union all
select 'pele#1-futbol.br may not work' from dual union all
select 'sql#oracle.com, sam#att.net,solo#violin.com' from dual union all
select '' from dual union all
select 'this string contains no email addresses' from dual union all
select '-this:email#address.illegal_domain' from dual union all
select 'alpha#123.34.23.1 talk#radio#mike.com' from dual
)
select str as original_string,
level as idx,
regexp_substr(str, '[[:alnum:]_-]+#[[:alnum:]_-]+\.[[:alnum:]_-]+', 1, level)
as email_address
from input_strings
connect by regexp_substr(str, '[[:alnum:]_-]+#[[:alnum:]_-]+\.[[:alnum:]_-]+', 1, level)
is not null
and prior str = str
and prior sys_guid() is not null
;
ORIGINAL_STRING IDX EMAIL_ADDRESS
------------------------------------------- ---------- --------------------------------
-this:email#address.illegal_domain 1 email#address.illegal_domain
alpha#123.34.23.1 talk#radio#mike.com 1 alpha#123.34
alpha#123.34.23.1 talk#radio#mike.com 2 radio#mike.com
pele#1-futbol.br may not work 1 pele#1-futbol.br
sdss abc#gmail.com sdsda sdsds 1 abc#gmail.com
sql#oracle.com, sam#att.net,solo#violin.com 1 sql#oracle.com
sql#oracle.com, sam#att.net,solo#violin.com 2 sam#att.net
sql#oracle.com, sam#att.net,solo#violin.com 3 solo#violin.com
this string contains no email addresses 1
1
10 rows selected.
Try this (regular expression) :
select regexp_substr ('sdss abc#gmail.com sdsda sdsds ','[A-Za-z0-9._%+-]+#[A-Za-z0-9.-]+\.[A-Za-z]{2,4}') email from dual

Oracle RegExp_Like for Two Repeating Digits

I would like to write a regexp_like function which would identify if a string consists of two repeating characters. It would only identify a string that has alternating numbers and only consisting of two unique numbers, but the unique number cannot repeat, it must alternate.
Requirement :
Regular expression should match the pattern for 787878787, but it should NOT match the pattern 787878788
It should NOT consider the pattern like 000000000
I think you want the following:
WITH t1 AS (
SELECT '787878787' AS str FROM dual
UNION
SELECT '787878788' AS str FROM dual
UNION
SELECT '7878787878' AS str FROM dual
UNION
SELECT '78' AS str FROM dual
)
SELECT * FROM t1
WHERE REGEXP_LIKE(str, '^(.)(.)(\1\2)*\1?$')
AND SUBSTR(str, 1, 1) != SUBSTR(str, 2, 1)
This will cover the case (mentioned in the requirements) where the string ends with the same character with which it begins. If you want only digits, replace the . in the regex with \d.
Update:
Here is how the regex breaks down:
^ = start of string
(.) = first character - can be anything - in parentheses to capture it and use it in a backreference
(.) = second character - can be anything
\1 = backreference to first captured group
\2 = backreference to second captured group
(\1\2)* = These should appear together zero or more times
\1? = The first captured group should appear zero or one times
$ = end of the string
Hope this helps.
You might do something like this -
SQL> WITH DATA AS(
2 SELECT '787878787' str FROM dual UNION ALL
3 SELECT '787878788' FROM dual
4 )
5 SELECT *
6 FROM DATA
7 WHERE REGEXP_LIKE(str, '(\d+?)\1')
8 AND SUBSTR(str, 1,1) = SUBSTR(str, -1, 1)
9 /
STR
---------
787878787
SQL>
Since you are dealing only with digits, I used \d.
\d+? will match the digits, and, \1 are the captured digits. The substr in the AND condition is checking whether the first and last digit of the string are same.
Edit : Additional requirement by OP
To avoid the numbers like 00000000, you need to add a NOT condition to the predicate.
SQL> WITH DATA AS
2 ( SELECT '787878787' str FROM dual
3 UNION ALL
4 SELECT '787878788' FROM dual
5 UNION ALL
6 SELECT '787878788' FROM dual
7 )
8 SELECT *
9 FROM DATA
10 WHERE REGEXP_LIKE(str, '(\d+?)\1')
11 AND SUBSTR(str, 1,1) = SUBSTR(str, -1, 1)
12 AND SUBSTR(str, 2,1) <> SUBSTR(str, -1, 1)
13 /
STR
---------
787878787
SQL>
You could try:
^(..)\1*$
Breakdown:
^ - assert beginning of line
(..) - capture the first 2 characters
\1* - repeat the captured group pattern zero or more times
$ - assert end of line
Untested in oracle...