问题
I am looking for a way to replace (remove / replace with '') a character string in a comma-separated list of values in a column in an Oracle SQL database. For example, suppose I have the following data:
select ('SL,PK') as col1 from dual
union all
select ('PK,SL') as col1 from dual
union all
select ('SL,SL') as col1 from dual
union all
select ('SL') as col1 from dual
union all
select ('PK') as col1 from dual
union all
select ('PI,SL,PK') as col1 from dual
union all
select ('PI,SL,SL,PK') as col1 from dual
union all
select ('PI,SL,SL,SL,PK') as col1 from dual
union all
select ('PI,SL,SL,SL,SL,PK') as col1 from dual
union all
select ('PI,OSL,SL,PK') as col1 from dual
union all
select ('PI,SL,SLR,PK') as col1 from dual
COL1
-----
SL,PK
PK,SL
SL,SL
SL
PK
PI,SL,PK
PI,SL,SL,PK
PI,SL,SL,SL,PK
PI,SL,SL,SL,SL,PK
PI,OSL,SL,PK
PI,SL,SLR,PK
I am looking to replace all occurrences of the substring 'SL', strictly (i.e. not including 'OSL'), with an empty string, ''
. The ideal result would look like this:
COL2
-----
,PK
PK,
,
(null)
PK
PI,,PK
PI,,,PK
PI,,,,PK
PI,,,,,PK
PI,OSL,,PK
PI,,SLR,PK
I have tried to use the regexp_replace
function, but it only eliminates every other occurence, i.e.
SELECT
col1,
regexp_replace(col1,'(^|,)(SL)($|,)','\1' || '' || '\3',1,0,'imn') as col2
FROM (
SELECT ('SL,PK') as col1 FROM dual
UNION ALL
SELECT ('PK,SL') as col1 FROM dual
UNION ALL
SELECT ('SL,SL') as col1 FROM dual
UNION ALL
SELECT ('SL') as col1 FROM dual
UNION ALL
SELECT ('PK') as col1 FROM dual
UNION ALL
SELECT ('PI,SL,PK') as col1 FROM dual
UNION ALL
SELECT ('PI,SL,SL,PK') as col1 FROM dual
UNION ALL
SELECT ('PI,SL,SL,SL,PK') as col1 FROM dual
UNION ALL
SELECT ('PI,SL,SL,SL,SL,PK') as col1 FROM dual
UNION ALL
SELECT ('PI,OSL,SL,PK') as col1 FROM dual
UNION ALL
SELECT ('PI,SL,SLR,PK') as col1 FROM dual
)
COL1 COL2
----- -----
SL,PK ,PK
PK,SL PK,
SL,SL ,SL
SL (null)
PK PK
PI,SL,PK PI,,PK
PI,SL,SL,PK PI,,SL,PK
PI,SL,SL,SL,PK PI,,SL,,PK
PI,SL,SL,SL,SL,PK PI,,SL,,SL,PK
PI,OSL,SL,PK PI,OSL,,PK
PI,SL,SLR,PK PI,,SLR,PK
I have achieved my goal successfully in other regex implementations that have the word boundary \b
construct available, but have not found a solution for Oracle's regex.
UPDATE
- Version: We are on Oracle version 11g.
- Addition example case
PI,SL,SLR,PK
- Additional example cases
PK,SL
,SL,SL
,SL
,PK
回答1:
because Oracle's regex moves the matching position forward after a match you need to do regexp double times unfortunately
regexp_replace(regexp_replace(col1,'(^|,)(SL)(\W|$)','\1\3',1,0,'imn') ,'(^|,)(SL)(\W|$)','\1\3',1,0,'imn')
回答2:
If you can choose a special character that doesn't appear in the string - I'm using semicolon (;
) you may follow this steps
1) double each comma to comma + semicolon
2) perform your regexp only adding the semicolon as a possible delimiter to the pattern:
'(^|,|;)(SL)($|,|;)
3) remove all semicolons
The complete query
SELECT
replace(regexp_replace(replace(col1,',',',;'),'(^|,|;)(SL)($|,|;)','\1\3',1,0,'imn'),';') as col2
FROM tab;
produce the expected result
,PK
PK,
,
(null)
PK
PI,,PK
PI,,,PK
PI,,,,PK
PI,,,,,PK
PI,OSL,,PK
PI,,SLR,PK
来源:https://stackoverflow.com/questions/61940076/oracle-regex-replace-multiple-occurrences-of-a-string-surrounded-by-commas