2012-03-01 62 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 
相关问题