2011-08-14 57 views
0
... 
<td class="m92_t_col5" id="preis_0">xx</td> 
... 

我想改變MSSQL(TSQL)程序更換順序

... 
<td id="preis_0" class="m92_t_col5">xxx</td> 
... 

所以ID = 「」 必須先CLASS = 「」。這可能與tsql有關嗎?文本在id或類是通用的...

+0

你能解釋一下你想達到什麼樣的?爲什麼你需要改變這些屬性的順序? –

+0

becouse我正在解析一些數據,我需要id =「」class =「」 – senzacionale

+2

在客戶端代碼中調整這類事情比在sql中調整要容易很多,尤其是在這裏,你有html。去獲得一個真正的HTML解析器來在你的應用程序中使用。如果你關心訂單的代碼,你做錯了。 –

回答

2

我需要去找一些肥皂,但給你的要求,這是如何實現所需的替代品的一個例子。

-- 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 cases 
    select '<td class="m92_t_col5" id="preis_0">xx</td>' AS html 
    union all select '<td id="preis_2" class="m29_t_col5">no fix req</td>' 
    union all select '<td id="preis_49" class="m29_t_col5">no fix req</td>' 
    union all select '<td class="m93_t_col50" id="preis_3">xy</td>' 
    union all select '<td  class="m95_t_col5" style="fuzzy" id="preis_5">xz</td>' 
    union all select '<td id="preis_8" class="m29_t_col5">no fix req</td>' 
) 
, ORDINALS AS 
(
    -- Find the starting position of the keywords 
    SELECT 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 (ORDER BY (SELECT 1)) 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 position 
    SELECT 
     O.* 
    , CHARINDEX('"', O.html, O.class_ordinal+7) + 1 AS class_ordinal_end_quote 
    , CHARINDEX('"', O.html, O.id_ordinal+4) + 1 AS id_ordinal_end_quote 
    FROM 
     ORDINALS O 
    WHERE 
     O.id_ordinal > O.class_ordinal 
) 
, FIND_PARTS AS 
(
    -- strip out the parts 
    SELECT 
     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 
    UNION ALL 
    SELECT 
     O.html 
    , O.original_sequence 
    FROM 
     ORDINALS O 
    WHERE 
     O.id_ordinal < O.class_ordinal 

) 
SELECT 
    D.html 
FROM 
    DONE D 
ORDER BY 
    D.original_sequence 

輸入

<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> 

輸出

<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> 

做一些思考之後,你可能一直在試圖問,作爲一個標量函數。這可能會有更糟糕的表現,但它解決了這個問題。

-- Same logic as above, now in function form 
CREATE FUNCTION dbo.ClassIdSwap 
(
    @input varchar(max) 
) 
RETURNS varchar(max) 
AS 
BEGIN 
    DECLARE 
     @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) 
    BEGIN 
     RETURN @input 
    END 

    SELECT  
     @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 

使用

; 
WITH SAMPLE_DATA AS 
(
    -- gin up some demo data 
    -- with random spacing and ids to make valid test cases 
    select '<td class="m92_t_col5" id="preis_0">xx</td>' AS html 
    union all select '<td id="preis_2" class="m29_t_col5">no fix req</td>' 
    union all select '<td id="preis_49" class="m29_t_col5">no fix req</td>' 
    union all select '<td class="m93_t_col50" id="preis_3">xy</td>' 
    union all select '<td  class="m95_t_col5" style="fuzzy" id="preis_5">xz</td>' 
    union all select '<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 
+0

thx你救了我的一天。謝謝! – senzacionale