2012-09-10 77 views
1

我有一個表「tblRandomString」與下面的數據:多替換在SQL Server 2005

ID ItemValue 

1 *Test" 
2 ?Test* 

我有另一個表「tblSearchCharReplacement」與下面的數據

Original Replacement 

*   `star` 
?   `quest` 
"   `quot` 
;   `semi` 

現在,我想使用這些替換在ItemValues中進行替換。 我嘗試這樣做:

Update T1 
SET ItemValue = select REPLACE(ItemValue,[Original],[Replacement]) 
FROM dbo.tblRandomString T1 
JOIN 
dbo.tblSpecialCharReplacement T2 
ON T2.Original IN ('"',';','*','?') 

但它不幫我,因爲只有一個替換每次更新完成。

一個解決方案是我必須使用CTE來執行多個替換,如果它們存在。

有沒有更簡單的方法?

+1

其實,所有的更新換代確實是會發生 - 所有4個可能的結果計算,並行。然後SQL Server隨意將其中一個作爲「更新」應用。 –

+0

此外,我已經將您的示例表標記爲試圖讓它們更易於閱讀的代碼 - 但我有點不確定哪些字符是示例數據的一部分,vs您可能添加了嘗試格式化它們。 –

回答

2

的樣本數據:

declare @RandomString table (ID int not null,ItemValue varchar(500) not null) 
insert into @RandomString(ID,ItemValue) values 
(1,'*Test"'), 
(2,'?Test*') 

declare @SearchCharReplacement table (Original varchar(500) not null,Replacement varchar(500) not null) 
insert into @SearchCharReplacement(Original,Replacement) values 
('*','`star`'), 
('?','`quest`'), 
('"','`quot`'), 
(';','`semi`') 

而且UPDATE

;With Replacements as (
    select 
     ID,ItemValue,0 as RepCount 
    from 
     @RandomString 
    union all 
    select 
     ID,SUBSTRING(REPLACE(ItemValue,Original,Replacement),1,500),rs.RepCount+1 
    from 
     Replacements rs 
      inner join 
     @SearchCharReplacement scr 
      on 
       CHARINDEX(scr.Original,rs.ItemValue) > 0 
), FinalReplacements as (
    select 
     ID,ItemValue,ROW_NUMBER() OVER (PARTITION BY ID ORDER BY RepCount desc) as rn 
    from 
     Replacements 
) 
update rs 
    set ItemValue = fr.ItemValue 
from 
    @RandomString rs 
     inner join 
    FinalReplacements fr 
     on 
      rs.ID = fr.ID and 
      rn = 1 

主要生產:

select * from @RandomString 

ID   ItemValue 
----------- ----------------------- 
1   `star`Test`quot` 
2   `quest`Test`star` 

這樣做是它與不變的文本開始(頂部選擇Replacements),那麼它會嘗試應用任何有效的替換(第二個選擇i n Replacements)。它將做的是繼續應用這第二個選擇,根據它產生的結果,直到沒有新的行產生。這被稱爲遞歸公用表表達式(CTE)。

然後,我們使用第二個CTE(這次是一個非遞歸函數)FinalReplacements對第一個CTE產生的所有行進行編號,爲最後產生的行分配較低的行號。從邏輯上講,這些是應用上次適用轉換的結果,因此不再包含任何要替換的原始字符。因此,我們可以使用行號1對原始表執行更新。

該查詢確實做了比絕對必要的更多的工作 - 對於少量的替換字符行,它不太可能太低效。我們可以通過定義單一訂單來清除它,以便應用替代品。

+0

感謝您的解決方案。看起來沒有其他選擇。唯一的問題是我的實際問題稍微複雜一點。如果字符串包含在雙引號內,我不想替'*','?'做替換。只有'''和';'在這種情況下應該被替換,爲此,我相信我應該再多做一次CTE。 – Torpedo

0

跳過連接表和嵌套REPLACE函數是否工作? 或者您是否需要從其他表中獲取數據?

-- perform 4 replaces in a single update statement 
UPDATE T1 
SET ItemValue = REPLACE(
        REPLACE(
        REPLACE(
         REPLACE(
         ItemValue,'*','star') 
         ItemValue,'?','quest') 
        ItemValue,'"','quot') 
        ItemValue,';','semi') 

注:我不知道,如果你需要逃避任何字符要替換