Skip to content Skip to sidebar Skip to footer

Mssql (tsql) Procedure Replace Order

... xx ... i want to change to ... xxx ... So id='' must be first and th

Solution 1:

I need to go find some soap but given your requirements, this is an example of how to achieve the desired replacement.

-- This will probably not perform terribly well for a number of-- reasons, not the least of which we are doing lots of string manipulation-- within tsql.-- Much of this query nonsense could be consolidated into fewer queries-- but given the dearth of information, I chose to build out the solution-- in a tumbling data anti-pattern
;
WITH SAMPLE_DATA AS
(
    -- gin up some demo data-- with random spacing and ids to make valid test casesselect'<td class="m92_t_col5" id="preis_0">xx</td>'AS html
    unionallselect'<td id="preis_2" class="m29_t_col5">no fix req</td>'unionallselect'<td id="preis_49" class="m29_t_col5">no fix req</td>'unionallselect'<td  class="m93_t_col50" id="preis_3">xy</td>'unionallselect'<td      class="m95_t_col5" style="fuzzy" id="preis_5">xz</td>'unionallselect'<td id="preis_8" class="m29_t_col5">no fix req</td>'
)
, ORDINALS AS
(
    -- Find the starting position of the keywordsSELECT SD.*
    ,   CHARINDEX('class=', SD.html, 0) AS class_ordinal
    ,   CHARINDEX('id=', SD.html, 0) AS id_ordinal 
    -- You will really need something in here to keep stuff straight-- otherwise when we bring it all back together, it'll be wrong
    ,   ROW_NUMBER() OVER (ORDERBY (SELECT1)) AS original_sequence
    FROM SAMPLE_DATA SD 
)
, NEEDS_MODIFIED AS
(
    -- identify the rows that need modified-- and use the ordinals in previous query to find the close positionSELECT
        O.*
    ,   CHARINDEX('"', O.html, O.class_ordinal+7) +1AS class_ordinal_end_quote
    ,   CHARINDEX('"', O.html, O.id_ordinal+4) +1AS id_ordinal_end_quote
    FROM
        ORDINALS O
    WHERE
        O.id_ordinal > O.class_ordinal
)
, FIND_PARTS AS
(
    -- strip out the partsSELECT
        NM.*
    ,   SUBSTRING(NM.html, class_ordinal, class_ordinal_end_quote - class_ordinal) AS class
    ,   SUBSTRING(NM.html, id_ordinal, id_ordinal_end_quote - id_ordinal) AS id
    FROM
        NEEDS_MODIFIED NM
)
, DONE AS
(
    SELECT-- This is the heart of the matter-- having identified the correct text values for class and id-- we will now perform a triple replace-- Replace 1 is swapping the class text with somthing that should not exist in source-- Replace 2 replaces the id text with our class text-- Replace 3 removes our placeholder value with id
        REPLACE(REPLACE(REPLACE(FP.html, FP.class, '~~|~'), FP.id, FP.class), '~~|~', FP.id) AS html
    ,   FP.original_sequence
    FROM
        FIND_PARTS FP
    UNIONALLSELECT
        O.html
    ,   O.original_sequence
    FROM
        ORDINALS O
    WHERE
        O.id_ordinal < O.class_ordinal

)
SELECT
    D.html
FROM
    DONE D
ORDERBY
    D.original_sequence 

Input

<td class="m92_t_col5"id="preis_0">xx</td>
<td id="preis_2" class="m29_t_col5">no fix req</td>
<td id="preis_49" class="m29_t_col5">no fix req</td>
<td  class="m93_t_col50"id="preis_3">xy</td>
<td      class="m95_t_col5" style="fuzzy"id="preis_5">xz</td>
<td id="preis_8" class="m29_t_col5">no fix req</td>

Output

<td id="preis_0" class="m92_t_col5">xx</td>
<td id="preis_2" class="m29_t_col5">no fix req</td>
<td id="preis_49" class="m29_t_col5">no fix req</td>
<td  id="preis_3" class="m93_t_col50">xy</td>
<td      id="preis_5" style="fuzzy" class="m95_t_col5">xz</td>
<td id="preis_8" class="m29_t_col5">no fix req</td>

After doing some thinking, you might have been trying to ask for that as a scalar function. This will probably have even worse performance but it solves the problem.

-- Same logic as above, now in function formCREATEFUNCTION dbo.ClassIdSwap
(
    @inputvarchar(max)
)
RETURNSvarchar(max)
ASBEGINDECLARE@class_ordinal int
    ,   @class_text varchar(max)
    ,   @class_ordinal_end_quote int
    ,   @id_ordinal int
    ,   @id_text varchar(max)
    ,   @id_ordinal_end_quote int
    ,   @out_html varchar(max)

    SELECT@class_ordinal = CHARINDEX('class=', @input, 0) 
    ,   @id_ordinal = CHARINDEX('id=', @input, 0) 

    SELECT@class_ordinal_end_quote = CHARINDEX('"', @input, @class_ordinal+7) +1
    ,   @id_ordinal_end_quote = CHARINDEX('"', @input, @id_ordinal+4) +1-- bail out early
    IF (@id_ordinal <@class_ordinal)
    BEGINRETURN@inputENDSELECT@class_text =SUBSTRING(@input, @class_ordinal, @class_ordinal_end_quote -@class_ordinal)
    ,   @id_text =SUBSTRING(@input, @id_ordinal, @id_ordinal_end_quote -@id_ordinal)

    RETURN (REPLACE(REPLACE(REPLACE(@input, @class_text, '~~|~'), @id_text, @class_text), '~~|~', @id_text))

END

Usage

;
WITH SAMPLE_DATA AS
(
    -- gin up some demo data-- with random spacing and ids to make valid test casesselect'<td class="m92_t_col5" id="preis_0">xx</td>'AS html
    unionallselect'<td id="preis_2" class="m29_t_col5">no fix req</td>'unionallselect'<td id="preis_49" class="m29_t_col5">no fix req</td>'unionallselect'<td  class="m93_t_col50" id="preis_3">xy</td>'unionallselect'<td      class="m95_t_col5" style="fuzzy" id="preis_5">xz</td>'unionallselect'<td id="preis_8" class="m29_t_col5">no fix req</td>'
)
SELECT
    D.html  
,   dbo.ClassIdSwap(D.html) AS modified     
FROM
    SAMPLE_DATA D

Post a Comment for "Mssql (tsql) Procedure Replace Order"