我想在列(Oracle SQL)的特定文本范围内用另一个字符(?)替换一个字符(/)

时间:2019-03-18 19:17:35

标签: sql oracle replace

问题在于该列中包含很多文本,我只想在特定的文本范围内进行此更改。

在每个示例中,该列均填充有以下数据:

...

<PropertyBagV2>
            <Item Name="Inventory_Document">
                <ValueList>
                    <Value />
                </ValueList>
            </Item>
            <Item Name="SupplierPartnerNo">
                <ValueList>
                    <Value />
                </ValueList>
            </Item>
            <Item Name="LabelNumber">
                <ValueList>
                    <Value>253938478/L44704428</Value>
                </ValueList>
            </Item>
            <Item Name="PalletProductList">
                <ValueList>
                    <Value>L44704428/253938478/C01/NOUPLOAD/NOUPLOAD/1/MTPR/MTPR</Value>
                    <Value>L44704428/253938478/90099326/311/NOUPLOAD/10/MTPR/MTPR</Value>
                </ValueList>
            </Item>
        </PropertyBagV2>
    </SessionContext>

...

但是我只想将'/'用'?'替换成段'L%'到'/ MTPR <'。基本上,在这两个部分上:

<Value>L44704428/253938478/C01/NOUPLOAD/NOUPLOAD/1/MTPR/MTPR</Value>                 
<Value>L44704428/253938478/90099326/311/NOUPLOAD/10/MTPR/MTPR</Value>

在ORACLE中有没有办法做到这一点? 预先谢谢你。

最好的问候, 爱德华多

1 个答案:

答案 0 :(得分:0)

这是一个非常复杂的SQL语句,可以满足您的要求。我不知道如何将regexp_replace约束到带有值列表的行,所以我将文本分成多行,进行替换,然后重新组合。

WITH
-- Original value to be replaced
aset AS( SELECT q'[<PropertyBagV2>
        <Item Name="Inventory_Document">
            <ValueList>
                <Value />
            </ValueList>
        </Item>
        <Item Name="SupplierPartnerNo">
            <ValueList>
                <Value />
            </ValueList>
        </Item>
        <Item Name="LabelNumber">
            <ValueList>
                <Value>253938478/L44704428</Value>
            </ValueList>
        </Item>
        <Item Name="PalletProductList">
            <ValueList>
                <Value>L44704428/253938478/C01/NOUPLOAD/NOUPLOAD/1/MTPR/MTPR</Value>
                <Value>L44704428/253938478/90099326/311/NOUPLOAD/10/MTPR/MTPR</Value>
            </ValueList>
        </Item>
    </PropertyBagV2>
</SessionContext>]' AS t, CHR( 10 ) AS lf FROM DUAL ),
-- Split the record into multiple records using the trailing line feed as the separator
    splitit ( t
            , REMAINDER
            , lf
            , r ) AS
        (                         -- Ensure the last line is included by adding a trailing line feed
         SELECT SUBSTR( t || lf, 1, INSTR( t || lf, lf ) - 1 )     AS t
              , SUBSTR( t || lf, INSTR( t, lf ) + 1 )              AS REMAINDER
              , lf
              , 1                                                  AS r
           FROM aset
         UNION ALL
         SELECT SUBSTR( REMAINDER, 1, INSTR( REMAINDER, lf ) - 1 )     AS t
              , SUBSTR( REMAINDER, INSTR( REMAINDER, lf ) + 1 )        AS REMAINDER
              , lf
              , r + 1                                                  AS r
           FROM splitit
          WHERE REMAINDER IS NOT NULL AND t IS NOT NULL),
    repl AS
        (SELECT t
              ,                
              -- Only replace slashes on records starting with spaces and <value>L
              -- 'i' makes the match case insensitive
                CASE
                    WHEN REGEXP_LIKE( t, '^ *<value>L.*</value>$', 'i' )
                    THEN
                        -- I am using ' boo ' instead of odd character questioner
                        -- requested. Substitute your own string for ' boo '
                        REPLACE( t, '/', ' boo ' )
                    ELSE
                        -- no match, just return original string
                        t
                END    replaced
              , r
           FROM splitit)
-- LISTAGG will recombine the multiple records back into a single record
SELECT LISTAGG( replaced, CHR( 10 ) ) WITHIN GROUP (ORDER BY r)     AS t
  FROM repl