0

I have a column which has record in below specific format :-

ParamName1+ParamVal1;ParamName2+ParamVal2;ParamName3+ParamVal3;

Currently I am using below query logic but this logic also brings the value for which the part of the search ParamName matches :-

TRIM(REGEXP_REPLACE(REGEXP_SUBSTR(TO_CHAR(ITEM_ATRS_LIST),'ID\+[^;]*'),'ID\+',''))

For example if I have value EmpID+1234;Name+ABCD;Age+21; using query

TRIM(REGEXP_REPLACE(REGEXP_SUBSTR(TO_CHAR(ITEM_ATRS_LIST), 'ID\+[^;]*'),'ID\ + ',''))

gives us value 1234 but we want NULL since the ParamName ID is not present.

Do we have any way to bring value which matches completely with the search paramName ?

2
  • I'd use a programming language for this. PL/SQL comes to mind :-) Commented May 25, 2018 at 11:12
  • Do all those processing work in java,Don't pass this ugliness into database tables and sql code. :-) Commented May 25, 2018 at 11:23

2 Answers 2

1

You are looking for a value for an attribute, say for 'EmpID'. This is what I've come up with:

regexp_replace( regexp_substr(item_atrs_list, 
                              '(^|;)EmpID\+.*?(;|$)'
                             ),
                '^.*?\+(.*?)\;?$',
                '\1'
              )

Explantion for (^|;)EmpID\+.*?(;|$)':

  • (^|;) beginning of the string or a semicolon in the string
  • EmpID followed by EmpID
  • \+ followed by a plus sign
  • .*?(;|$)' maybe followed by some characters (the value), finally followed by a semicolon or hitting the end of the string

Explantion for '^.*?\+(.*?)\;?$':

  • ^ the beginning of the string
  • ^.*?\+ possibly followed by some characters, then a plus sign (i.e. ';EmpID+' or 'EmpID+')
  • (.*?)\;?$' possibly followed by some characters that we memorize (the value), then possibly a semicolon, then the end of the string

Explantion for \1:

  • The first (and only) string we memorized, i.e. the value

(I'm not that good with regular expressions. There may be a much easier way to achieve this. As mentioned I would rather use a programming language such as PL/SQL anyway.)

Sign up to request clarification or add additional context in comments.

Comments

1

Here's another way to approach it using Common Table Expressions (CTE's). The first one, 'tbl', just sets up a source for the original data. 'params' creates a table of name-value pairs, looping using connect by and splitting on the separator of a semi-colon, then further by the plus sign. Then, just select from there where your name matches.

-- Original data
with tbl(data) as (
  select 'EmpID+1234;Name+ABCD;Age+21;' from dual
),
-- make a table of name-value pairs
params(name, value) as (
  select regexp_substr(data, '(^|;)(.*?)\+', 1, level, NULL, 2),
         regexp_substr(data, '\+(.*?)(;|$)', 1, level, NULL, 1)
  from tbl
  connect by level <= regexp_count(data, ';')
)
--select * from params;
-- Get the value for the name
select name, value
from params
where name = 'EmpID';

2 Comments

I think this is a much nicer generic solution
Just another way to approach the problem. Turning the name-value pairs into a table may give more flexibility on working with the data but maybe at the expense of some performance if the data set could be large. As usual one should test with one's own data and needs and weigh the pro's and cons. Information is power!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.