2012-03-01 118 views
0

我有一個包含約50個表的數據庫,每個表都有大約10-100列,每個表中最多有1000萬行。 (相當大,像一個新手:P)在表中的特定列中的所有行中查找特殊字符

數據庫是舊的,有些行包含特殊字符(不可見的字符或一些奇​​怪的Unicode),我想刪除這些字符。

我在谷歌搜索,我發現了一個小片段,列出了特定類型的所有列:

SELECT 
    OBJECT_NAME(col.OBJECT_ID) AS [TableName] 
    ,col.[name] AS [ColName] 
    ,typ.[name] AS [TypeName] 
FROM 
    sys.all_columns col 
    INNER JOIN sys.types typ 
    ON col.user_type_id = typ.user_type_id 
WHERE 
    col.user_type_id IN (167,231) 
    AND 
    OBJECT_NAME(col.OBJECT_ID) = 'Orders' 

此列出了爲varchar或nvarchar的所有列。

我發現了兩個功能,一個是返回所有字符的表從一個字符串和第二,檢查是否字符串包含任何特殊字符:

CREATE FUNCTION AllCharactersInString (@str nvarchar(max)) 
RETURNS TABLE 
AS 
RETURN 
    (SELECT 
     substring(B.main_string,C.int_seq,1) AS character 
    ,Unicode(substring(B.main_string,C.int_seq,1)) AS unicode_value 
    FROM 
     (SELECT 
     @str AS main_string) B,(SELECT 
           A.int_seq 
           FROM 
            (SELECT 
            row_number() OVER (ORDER BY name) AS int_seq 
            FROM 
            sys.all_objects) A 
            WHERE 
            A.int_seq <= len(@str)) C 
    ) 

其次:

CREATE FUNCTION ContainsInvisibleCharacter (@str nvarchar(max)) 
RETURNS int 
AS 
BEGIN 
DECLARE @Result Int 
IF exists 
(SELECT 
    * 
    FROM 
    AllCharactersInString(@str) 
    WHERE 
    unicode_value IN (1,9,10,11,12,13,14,28,29,31,129,141,143,144,157,160)) 
BEGIN SET @Result = 1 
    END 
ELSE 
BEGIN SET @Result = 0 
    END 
RETURN @Result 
END 

我的問題是如何將兩個函數合併爲一個(如果可能並且速度更快),第二個:如何在表中的所有列(特定類型)中的所有記錄上運行該函數。

我有這樣的代碼:

SELECT 
    O.Order_Id 
    ,Rn_Descriptor 
FROM 
    dbo.Order O 
WHERE 
    dbo.ContainsInvisibleCharacter(O.Rn_Descriptor) = 1 
    AND 
    O.Order_Id IN (SELECT TOP 1000 
          Order.Order_Id 
         FROM 
          dbo.Order 
         WHERE 
          Order.Rn_Descriptor IS NOT NULL 
        ) 

但它的工作原理SOOO緩慢:/ Mayby有刪除不想要的字符一個最快的方法? 什麼是罰款是找到包含這些字符的行,列出它們,然後我可以手動檢查它們。

回答

1

您可以使用LIKE更有效地做到這一點。

CREATE FUNCTION ContainsInvisibleCharacter(@str nvarchar(max)) RETURNS int 
AS 
BEGIN 
    RETURN 
     (SELECT CASE WHEN @str LIKE 
     '%[' + NCHAR(1) + NCHAR(9) + NCHAR(10) + NCHAR(11) + NCHAR(12) 
      + NCHAR(13) + NCHAR(14) + NCHAR(28) + NCHAR(29) + NCHAR(31) 
      + NCHAR(129) + NCHAR(141) + NCHAR(143) + NCHAR(144) 
      + NCHAR(157) + NCHAR(160) + ']%' 
     THEN 1 ELSE 0 END) 
END 
相關問題