Sql Oracle正则表达式替换多次出现的由逗号包围的字符串

Sql Oracle正则表达式替换多次出现的由逗号包围的字符串,sql,regex,oracle,oracle11g,regexp-replace,Sql,Regex,Oracle,Oracle11g,Regexp Replace,我正在寻找一种方法来替换Oracle SQL数据库中列中以逗号分隔的值列表中的字符串(删除/替换为“”)。例如,假设我有以下数据: 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 sele

我正在寻找一种方法来替换Oracle SQL数据库中列中以逗号分隔的值列表中的字符串(删除/替换为“”)。例如,假设我有以下数据:

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
我希望用空字符串“
”替换所有出现的子字符串“SL”(即不包括“OSL”)理想结果如下所示

COL2
-----
,PK
PK,
,
(null)
PK
PI,,PK
PI,,,PK
PI,,,,PK
PI,,,,,PK
PI,OSL,,PK
PI,,SLR,PK
我曾尝试使用
regexp\u replace
函数,但它只会消除所有其他情况,即

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
我已经在其他regex实现中成功地实现了我的目标,这些实现具有word boundary
\b
结构,但还没有为Oracle的regex找到解决方案

更新

  • 版本:我们使用的是Oracle版本11g
  • 添加示例案例
    PI、SL、SLR、PK
  • 其他示例案例
    PK,SL
    SL,SL
    SL
    PK

  • 因为Oracle的正则表达式在匹配后将匹配位置向前移动,所以不幸的是,您需要执行两次正则表达式

    regexp_replace(regexp_replace(col1,'(^|,)(SL)(\W|$)','\1\3',1,0,'imn') ,'(^|,)(SL)(\W|$)','\1\3',1,0,'imn')
    

    如果您可以选择一个不出现在字符串中的特殊字符-我使用分号(
    ),您可以按照以下步骤操作

    1) 将每个逗号加倍为逗号+分号

    2) 执行regexp时,仅将分号作为可能的分隔符添加到模式中:

    '(^|,|;)(SL)($|,|;) 
    
    3) 删除所有分号

    完整查询

    SELECT 
        replace(regexp_replace(replace(col1,',',',;'),'(^|,|;)(SL)($|,|;)','\1\3',1,0,'imn'),';') as col2
    FROM tab;
    
    产生预期的结果

    ,PK
    PK,
    ,
    (null)
    PK
    PI,,PK
    PI,,,PK
    PI,,,,PK
    PI,,,,,PK
    PI,OSL,,PK
    PI,,SLR,PK
    

    你使用的是什么版本的甲骨文?@wolφi很抱歉排除了这些信息。我们使用的是11g。不幸的是,如果逗号前面的“SL”后面还有其他字母,则此操作将不起作用。与“OSL”示例中之前可能有字母的方式类似,后面可能有字母,即“SLR”。我也在问题中添加了这个例子。那么,我看不到比用替补进行第二次传球更好的选择了<代码>regexp|u replace(regexp|u replace(col1),(^ |,)(SL)(\W |$),“\1\3',1,0,'imn'),”(^ |,)(SL)(\W |$),“\1\3',1,0,'imn')你提到这很有趣,这正是我在尝试不同场景时偶然发现的。如果您想将其添加为答案,我将接受。可以使用单个
    regexp\u replace
    (带有一些
    replace
    预处理和后处理)-请参阅备选答案。