Как я могу найти символы Unicode/non-ASCII в поле NTEXT в таблице SQL Server 2005?

В Chrome откройте инструменты разработчика и нажмите на вкладку сети. 90% времени вы можете определить медленный ресурс оттуда.

34
задан TheSoftwareJedi 26 March 2009 в 18:15
поделиться

6 ответов

Это - вероятно, не лучшее решение, но возможно запрос как:

SELECT *
FROM yourTable
WHERE yourTable.yourColumn LIKE '%[^0-9a-zA-Z]%'

Замените "0-9a-zA-Z" выражение чем-то, что получает полный набор ASCII (или подмножество, которое Ваши данные содержат).

2
ответ дан 27 November 2019 в 16:25
поделиться

Сначала создайте строку со всеми символами, Вы не интересуетесь (пример использует 0x20 - 0x7F диапазон, или 7 битов без управляющих символов.) Каждый символ снабжается префиксом | для использования в пункте Escape позже.

-- Start with tab, line feed, carriage return
declare @str varchar(1024)
set @str = '|' + char(9) + '|' + char(10) + '|' + char(13)

-- Add all normal ASCII characters (32 -> 127)
declare @i int
set @i = 32
while @i <= 127
    begin
    -- Uses | to escape, could be any character
    set @str = @str + '|' + char(@i)
    set @i = @i + 1
    end

Следующий отрывок ищет любой символ, который не находится в списке. % соответствует 0 или больше символам. [] соответствует одному из символов в [], например [abc] соответствовал бы или a, b или c. ^ инвертирует список, например [^abc] соответствовал бы чему-либо, что это не a, b, или c.

select *
from yourtable
where yourfield like '%[^' + @str + ']%' escape '|'

Символ ESC требуется, потому что, иначе ища символы как], % или _ испортил бы ПОДОБНОЕ выражение.

Надежда это полезно, и благодаря комментарию JohnFX к другому ответу.

17
ответ дан 27 November 2019 в 16:25
поделиться

Мой предыдущий ответ путал данные UNICODE/non-UNICODE. Вот решение, которое должно работать на все ситуации, хотя я все еще сталкиваюсь с некоторыми аномалиями. Кажется, что определенный неASCII unicode символы для символов надстрочного индекса путается с фактическим символом числа. Вы смогли играть вокруг с сопоставлениями для обхождения этого.

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

Вы также, возможно, должны были бы играть вокруг с числовым диапазоном, так как unicode символы может пойти вне 255.

CREATE TABLE dbo.Numbers
(
    number  INT NOT NULL,
    CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (number)
)
GO
DECLARE @i INT

SET @i = 0

WHILE @i < 1000
BEGIN
    INSERT INTO dbo.Numbers (number) VALUES (@i)

    SET @i = @i + 1
END
GO

SELECT *,
    T.ID, N.number, N'%' + NCHAR(N.number) + N'%'
FROM
    dbo.Numbers N
INNER JOIN dbo.My_Table T ON
    T.description LIKE N'%' + NCHAR(N.number) + N'%' OR
    T.summary LIKE N'%' + NCHAR(N.number) + N'%'
and t.id = 1
WHERE
    N.number BETWEEN 127 AND 255
ORDER BY
    T.id, N.number
GO
0
ответ дан 27 November 2019 в 16:25
поделиться

. Это очень и очень неэффективный способ сделать это, но он должен быть в порядке для - небольшие столики. Он использует вспомогательную таблицу чисел по Ицику Бен-Гану и просто - ищет символы с установленным битом 7.

SELECT  *
FROM    yourTable as t
WHERE   EXISTS ( SELECT *
                 FROM   msdb..Nums as NaturalNumbers
                 WHERE  NaturalNumbers.n < LEN(t.string_column)
                        AND ASCII(SUBSTRING(t.string_column, NaturalNumbers.n, 1)) > 127)  
-1
ответ дан 27 November 2019 в 16:25
поделиться

Технически я считаю, что NCHAR (1) является допустимым символом ASCII IF & Only IF UNICODE (@NChar) <256 и ASCII (@NChar) = UNICODE (@NChar), хотя это может быть не совсем то, что вы намеревались. Поэтому это было бы правильным решением:

;With cteNumbers as
(
    Select ROW_NUMBER() Over(Order By c1.object_id) as N
    From sys.system_columns c1, sys.system_columns c2
)
Select Distinct RowID
From YourTable t
    Join cteNumbers n ON n <= Len(CAST(TXT As NVarchar(MAX)))
Where UNICODE(Substring(TXT, n.N, 1)) > 255
    OR UNICODE(Substring(TXT, n.N, 1)) <> ASCII(Substring(TXT, n.N, 1))

Это тоже должно быть очень быстрым.

256 и ASCII (@NChar) = UNICODE (@NChar), хотя это может быть не совсем то, что вы намеревались. Поэтому это было бы правильным решением:

;With cteNumbers as
(
    Select ROW_NUMBER() Over(Order By c1.object_id) as N
    From sys.system_columns c1, sys.system_columns c2
)
Select Distinct RowID
From YourTable t
    Join cteNumbers n ON n <= Len(CAST(TXT As NVarchar(MAX)))
Where UNICODE(Substring(TXT, n.N, 1)) > 255
    OR UNICODE(Substring(TXT, n.N, 1)) <> ASCII(Substring(TXT, n.N, 1))

Это тоже должно быть очень быстрым.

256 и ASCII (@NChar) = UNICODE (@NChar), хотя это может быть не совсем то, что вы намеревались. Поэтому это было бы правильным решением:

;With cteNumbers as
(
    Select ROW_NUMBER() Over(Order By c1.object_id) as N
    From sys.system_columns c1, sys.system_columns c2
)
Select Distinct RowID
From YourTable t
    Join cteNumbers n ON n <= Len(CAST(TXT As NVarchar(MAX)))
Where UNICODE(Substring(TXT, n.N, 1)) > 255
    OR UNICODE(Substring(TXT, n.N, 1)) <> ASCII(Substring(TXT, n.N, 1))

Это тоже должно быть очень быстрым.

3
ответ дан 27 November 2019 в 16:25
поделиться

Я иногда использовал этот оператор "cast", чтобы найти "странные" символы

select 
    *
from 
    <Table>
where 
    <Field> != cast(<Field> as varchar(1000))
52
ответ дан 27 November 2019 в 16:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: