How to add characters in sql between two strings? - oracle

I'd like to know is it possible to add characters between two or more string using LPAD in SQL example sentence 'The Cat Is Sleeping'
LPAD('string', number, '+')
expected results:
++++++The+++++Cat+++++++Is++++++Sleeping
pas :-amount of + above is just an example maybe the result will be different. I hope you can understand my question.
if you are willing give me the exact query
thanks

Your problem is a good candidate for doing a regex replacement with REGEXP_REPLACE:
SELECT REGEXP_REPLACE(input, '^| ', '+++++++') AS output
FROM yourTable;
The output is:
+++++++The+++++++Cat+++++++Is+++++++Sleeping
Demo
Data:
WITH yourTable AS (
SELECT 'The Cat Is Sleeping' AS input FROM dual
)

Related

Having issue with extracing date from CLOB data

Hi I am having issue when extracting fields from CLOB data. For one record I am not getting desired output.
The record is as below:
{1:F014243107336}{2:O2021216200422XXX24563}{3:{108:O2020}{121:2c02a452-5}{433:HIT}}{4:
:4A:SEC:20200901
:4B:FC5253
:4C:20042000,
:4D:XXXXXXX
:4E:RXX
:4F:RXXXX
-}{5:{CHK:87D1003B01F7}{TNG:}}{S:{SAC:}{COP:S}}<APSECSIGN>FS3sfasdfg!==</APSECSIGN>?
I want to extract data from tag :4A: into REF_NUMBER.
I am using below SQL to get the data.
NVL(TRIM(TRANSLATE(REGEXP_REPLACE(REGEXP_SUBSTR(dbms_lob.substr(CLOB, 4000, 1 ), ':4A.?:[^:]+(:|-\})'), ':20.?:([^:]+)(:|-\})', '\1'),CHR(10)||CHR(13), ' ')),' ') AS REF_NUMBER
the output I am getting is "SEC". However I want to see output as SEC:20200901.
Can any one suggest what I am missing in my query or provide me correct query.
A general suggestion. Why don't you have your data stored as JSON ? Because, JSON related functions are very fast when compared to others. And then your problem becomes quite easy.
However to answer your question:
with inputs (str) as
(
select to_clob(q'<
{1:F014243107336}{2:O2021216200422XXX24563}{3:{108:O2020}{121:2c02a452-5}{433:HIT}}{4:
:4A:SEC:20200901
:4B:FC5253
:4C:20042000,
:4D:XXXXXXX
:4E:RXX
:4F:RXXXX
-}{5:{CHK:87D1003B01F7}{TNG:}}{S:{SAC:}{COP:S}}<APSECSIGN>FS3sfasdfg!==</APSECSIGN>?
>') from dual
)
select str, regexp_substr(str,'SEC:\d+',1,1,'n') as val
from inputs;
Output:
Updated
If you know the date is always going to be 8 digits after the :4A: tag, you can use REGEXP_SUBSTR to get the value you need. Combining it with DBMS_LOB.SUBSTR removes the tag and converts it to a string.
SELECT DBMS_LOB.SUBSTR ((REGEXP_SUBSTR (clob_val, ':4A:.*\d{8}')), 4000, 5)
FROM (SELECT EMPTY_CLOB ()
|| '{1:F014243107336}{2:O2021216200422XXX24563}{3:{108:O2020}{121:2c02a452-5}{433:HIT}}{4:
:4A:SEC:20200901
:4B:FC5253
:4C:20042000,
:4D:XXXXXXX
:4E:RXX
:4F:RXXXX
-}{5:{CHK:87D1003B01F7}{TNG:}}{S:{SAC:}{COP:S}}<APSECSIGN>FS3sfasdfg!==</APSECSIGN>?' AS clob_val
FROM DUAL);

Oracle regex_replace not working as expected

I have following SQL query (Oracle 18c):
SELECT
--FIRST
translate(
' sOmE tEsT
eNdOfLiNe',
chr(10)||chr(11)||chr(13), 'replText'
) "Result1",
--SECOND
regexp_replace(
' sOmE tEsT
eNdOfLiNe',
'[\x0A|\x0B|`\x0D]', 'replText'
) "Result2",
--THIRD
regexp_replace(
' sOmE tEsT
eNdOfLiNe',
'[\r\n\t]', 'replText', 1, 0
) "Result3"
FROM dual
What I would like to do is replace all tabs, return carriages and new line indicators with new string but it seems like regexp replace is not working (returns initial text). I am really sorry about formatting but I need to handle text in exact format as above with \r \n \t mixed chars.
Here is fiddle: https://dbfiddle.uk/?rdbms=oracle_18&fiddle=63834f9bcab93136635366f18c375b13
I am learning Oracle right now and don't understand why second and third solution returns initial text. The first solution seems to work but I would like to achieve the same effect in SECOND and THIRD solution. What I missed?
I'm pretty sure Oracle does not allow escape sequences in a character class. I believe this is what you have to do. In response to your comment on another answer here and as you are learning, regex is most definitely not regex. Especially Oracle's implementation.
EDIT to explain the regex: The regex pattern is building a string of a regex character class containing 3 characters, hence the concatenation. You can't just have escape characters in the regex as then regex would take those characters as part of the character class pattern itself.
SELECT REGEXP_REPLACE(
' sOmE tEsT
eNdOfLiNe', '['||CHR(9)||CHR(10)||CHR(13)||']', 'X') Result3
FROM dual;
RESULT3
------------------------------
sOmE tEsTXXXXXXXX eNdOfLiNe
1 row selected.
You can try the below using similar format as translate
select regexp_replace(
' sOmE tEsT
eNdOfLiNe',
chr(10)||'|'||chr(11)||'|'||chr(13), 'replText') "Result3"
FROM dual

Oracle string operation to exclude specific characters based on delimiter

From the String ES-123456-PSA Spain-101, I need to extract only ES-123456-101 Delimiter position is fixed.
Tried REGEXP_SUBSTR('ES-123456-PSA Spain-101','[^-]+',2,3 ) which gives PSA Spain.
Is there a way to ignore those specific characters and returns rest of them.
If you want ES-123456-101 then use this:
SELECT REGEXP_REPLACE('ES-123456-PSA Spain-101', '[^-]+-', '', 1, 3 )
FROM dual;
If you want ES-12345-101 then could you explain the logic for 12345 not 123456? Typo or omit the last character?
you can also use subtr and instr
with t as
(
select 'ES-123456-PSA Spain-101' as text from dual
)
select substr(text,1,instr(text,'-',1,2)) -- ES-123456-
||substr(text,instr(text,'-',1,3)+1) -- 101
from t

PL/SQL Stored proc that uses a comma separated parameter to drive a dynamic LIKE clause?

Is there a fairly simple way to take an input parameter containing a comma seperated list of prefixes and return a cursor based on a select statement that uses these?
i.e. (Pseudocode)
PROCEDURE get_by_prefix(p_list_of_prefixes IN varchar2, r_csr OUT SYS_REFCURSOR)
IS
BEGIN
OPEN r_csr FOR
SELECT * FROM my_table where some_column LIKE (the_individual_fields_from p_list_of_prefixes ||'%')
END
I've tried various combinations, and now have two problems - coercing the input into a suitable table (I think it needs to go into a table type rather than a VARCHAR2_TABLE), and secondly getting the like clause to be effectively a SELECT from an internal 'pseudotable'...
EDIT: It seems that people are suggesting ways to use 'IN' with a set of potential values - whereas Im looking at using LIKE. I could use a similar technique - building up dynamic SQL, but was wondering if there isnt a more elegant way...
PL/SQL has no concept of a comma-separated list and no built-in splitter as in Perl etc, so you'll have to use one of the hand-rolled methods such as this one:
https://stewashton.wordpress.com/2016/08/01/splitting-strings-surprise
(Other methods are available.) Then it's just a matter of either populating a collection in one step and using it in the next, or else combining the two as something like this:
declare
p_list_of_prefixes varchar2(100) := 'John,Jim,Jules,Janice,Jenny';
begin
open :refcur for
with params as
( select x.firstname
from xmltable(
'ora:tokenize($X, "\,")'
passing p_list_of_prefixes as x
columns firstname varchar2(4000) path '.'
) x
)
, people as
( select 'Dave Clark' as fullname from dual union all
select 'Jim Potter' from dual union all
select 'Jenny Jones' from dual
)
select x.firstname, p.fullname
from params x
left join people p on p.fullname like x.firstname || '%';
end;
Output:
FIRSTNAME FULLNAME
-------------- -----------
John
Jim Jim Potter
Jules
Janice
Jenny Jenny Jones
Using LIKE the way you want is easy, but it is the wrong solution. (See my Comment under the original post).
Anyway - if by order of your superiors, or some other semi-legitimate reason, you must use a LIKE condition, it should look something like this:
... where ',' || p_list_of_whatever || ',' like '%,' || some_column || ',%
Concatenating commas at both ends of both sides of the comparison is needed, because you don't want Jo in the column to match John in the input list. Start from there and you will see why you need the commas on the right-hand side, and then follow from there and you will see why you need them on the left also.

REGEXP_SUBSTR for portion of string

I would like to get:
82961_01B04WZXQQSUGJ4YMRRT2A7TRHK_MR_2_1of1
from the following expression
LASTNAME_FIRSTNAME_82961_01B04WZXQQSUGJ4YMRRT2A7TRHK_MR_2_1of1
Does someone know how I can get this using regexp_substr ?
EDIT
Basically I have a field which has 7 sets each separated by _ . The string I gave is just one example. I wanted to retrieve everything after the second _ . There is no fixed character length so I can not use a substr function. Hence I was using regexp_substr. I was able to get away by using a simplified version
Select FILE_NAME, ( (REGEXP_SUBSTR(FILE_NAME,'[^_]+_',1,3)) ||
(REGEXP_SUBSTR(FILE_NAME,'[^_]+_',1,4)) ||
(REGEXP_SUBSTR(FILE_NAME,'[^_]+_',1,5)) ||
(REGEXP_SUBSTR(FILE_NAME,'[^_]+_',1,6)) ||
(REGEXP_SUBSTR(FILE_NAME,'[^_]+',1,7)) ) as RegExp
from tbl
Here is some more data from the FILE_NAME field
LAST_FIRST_82961_01B04WZXQQSUGJ4YMRRT2A7TRHK_MR_2_1of1
SMITH_JOHN_82961_0130BPQX9QZN9G4P5RDTPA9HR4R_MR_1_1of1
LASTNAME_FIRSTNAME_99999_01V0MU4XUQK0Y24Y9RYTFA7W1CM_MR_3_1of1
To get everything after the second underscore, you do not need regular expressions, but can use something like the following:
select substr(FILE_NAME, instr(FILE_NAME, '_', 1, 2) +1 ) from tbl
The instr returns the position of the second occurrence of '_', starting by the first character; the substr simply gets everything starting from the position given by instr + 1
From your Requirement, you can just go ahead and use the simple SUBSTRfunction. Its faster, and it addresses the simple need to remove the String LASTNAME_FIRSTNAME.
select substr('LASTNAME_FIRSTNAME_82961_01B04WZXQQSUGJ4YMRRT2A7TRHK_MR_2_1of1', 20) data_string
from dual;
Output:
data_string
-----------------
82961_01B04WZXQQSUGJ4YMRRT2A7TRHK_MR_2_1of1
Unless you have another underlying logic you need to address?
Kindly clarify so i can edit the answer accordingly.

Resources