Найти специальные символы во всех строках в определенных столбцах таблицы - PullRequest
0 голосов
/ 01 марта 2012

У меня есть база данных, содержащая около 50 таблиц, каждая таблица имеет около 10-100 столбцов с максимум 1 миллион строк в каждой таблице. (довольно большой, как для новичка: P)

База данных старая и некоторые строки содержат специальные символы (невидимые символы или какой-то странный юникод), и я хотел бы удалить эти символы.

Я искал в Google и нашел небольшой фрагмент, в котором перечислены все столбцы определенного типа:

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
                      )

но работает ооочень медленно: / Может, есть самый быстрый способ удалить нежелательных персонажей? Что будет хорошо, так это найти строки, содержащие эти символы, перечислить их, и тогда я смогу проверить их вручную.

1 Ответ

1 голос
/ 17 марта 2012

Вы можете сделать это более эффективно, используя 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
...