2017-07-24 65 views
4

我目前正在處理某些問題,其中某些字符需要從表中存在的字符串中清除。通常我會做一個簡單的更新替換,但在這種情況下,有32個不同的字符需要刪除。高效清理表中的字符串

我已經做了一些環顧四周,找不到任何優秀的解決方案來快速清理已存在於表格中的字符串。

事情我已經看着:

  1. 做一系列嵌套內容替換

    的該解決方案是做,能幹,但對32種不同取代它需要一些既醜陋的代碼,或者哈克動態的sql來構建一個巨大的系列替換。

  2. PATINDEX和while循環

    this answer看到它可以模仿一種正則表達式替換,但我有很多數據的工作,所以我很猶豫,甚至改進方案信任當數據量很大時,在合理的時間內運行。

  3. 遞歸的CTE

    我嘗試了CTE approuch這個問題,但它沒有運行非常快,一旦行的數量得到了較大。

參考:

CREATE TABLE #BadChar(
    id int IDENTITY(1,1), 
    badString nvarchar(10), 
    replaceString nvarchar(10) 

); 

INSERT INTO #BadChar(badString, replaceString) SELECT 'A', '^'; 
INSERT INTO #BadChar(badString, replaceString) SELECT 'B', '}'; 
INSERT INTO #BadChar(badString, replaceString) SELECT 's', '5'; 
INSERT INTO #BadChar(badString, replaceString) SELECT '-', ' '; 

CREATE TABLE #CleanMe(
    clean_id int IDENTITY(1,1), 
    DirtyString nvarchar(20) 
); 

DECLARE @i int; 
SET @i = 0; 
WHILE @i < 100000 BEGIN 
    INSERT INTO #CleanMe(DirtyString) SELECT 'AAAAA'; 
    INSERT INTO #CleanMe(DirtyString) SELECT 'BBBBB'; 
    INSERT INTO #CleanMe(DirtyString) SELECT 'AB-String-BA'; 
    SET @i = @i + 1 
END; 


WITH FixedString (Step, String, cid) AS (
    SELECT 1 AS Step, REPLACE(DirtyString, badString, replaceString), clean_id 
    FROM #BadChar, #CleanMe 
    WHERE id = 1 

    UNION ALL 

    SELECT Step + 1, REPLACE(String, badString, replaceString), cid 
    FROM FixedString AS T1 
    JOIN #BadChar AS T2 ON T1.step + 1 = T2.id 
    Join #CleanMe AS T3 on T1.cid = t3.clean_id 

) 
SELECT String FROM FixedString WHERE step = (SELECT MAX(STEP) FROM FixedString); 

DROP TABLE #BadChar; 
DROP TABLE #CleanMe; 
  • 使用CLR

    看起來這是一個通用的解決方案很多人都用,但環境我「進來並不是一件容易的事。

  • 有沒有其他方法可以解決這個問題?或者我已經研究過的方法有什麼改進?

    +3

    什麼版本的SQL Server?在極不可能的情況下,你在2017年也有['Translate'](https://docs.microsoft.com/en-us/sql/t-sql/functions/translate-transact-sql),儘管這是隻是語法糖嵌套取代。 –

    +0

    您可以將數據提取到某個ETL工具,並在那裏執行操作,而不會高度依賴數據庫功能。例如,調查使用Community Edition免費的Pentaho數據集成。 –

    +4

    嵌套替換速度非常快。爲了上帝的緣故,不要爲了簡單的事情而啓動CLR或ETL。做嵌套替換,確保它在語法上有點難看,但不是什麼大不了的。 –

    回答

    1

    利用Alan Burstein's solution的想法,如果你想硬編碼壞/替換字符串,你可以做這樣的事情。這將適用於壞/替換字符串長於單個字符。

    CREATE FUNCTION [dbo].[CleanStringV1] 
    (
        @String nvarchar(4000) 
    ) 
    RETURNS nvarchar(4000) WITH SCHEMABINDING AS 
    BEGIN 
    SELECT @string = REPLACE 
        (
        @string COLLATE Latin1_General_BIN, 
        badString, 
        replaceString 
    ) 
    FROM 
    (VALUES 
         ('A', '^') 
        , ('B', '}') 
        , ('s', '5') 
        , ('-', ' ') 
        ) t(badString, replaceString) 
    RETURN @string; 
    END; 
    

    或者,如果你有一個包含壞表/替換字符串,然後

    CREATE FUNCTION [dbo].[CleanStringV2] 
    (
        @String nvarchar(4000) 
    ) 
    RETURNS nvarchar(4000) AS 
    BEGIN 
    SELECT @string = REPLACE 
        (
        @string COLLATE Latin1_General_BIN, 
        badString, 
        replaceString 
    ) 
    FROM BadChar 
    RETURN @string; 
    END; 
    

    這些是區分大小寫的。如果你想不區分大小寫,你可以刪除COLLATE位。我做了一些小測試,並且這些測試並沒有比嵌套REPLACE慢很多。硬編碼字符串的第一個是兩者中速度較快的,幾乎和嵌套REPLACE一樣快。