2017-01-04 3 views
1

Я использую следующие коды, чтобы определить, что описание содержит не-ascii.число символов ascii> число символов не-ascii в sql

Теперь я хочу установить условие Число символов ascii> количество символов не-ascii в описании, как я должен писать его в инструкции SQL?

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 

--select description, locale 
select description, productlocale, locale 
    FROM [DataExtraction].[dbo].[Feedback] 
    where 
and description like '%[^' + @str + ']%' escape '|' 

ответ

0

Может использовать функцию:

create function dbo.fn_CountAscii(@str varchar(8000)) 
returns int 
as 
begin 
declare @i int = 1 
declare @n int = 0 
while @i <= len(@str) 
begin 
    if ascii(substring(@str, @i, 1)) between 32 and 127 
    begin 
     set @n = @n + 1 
    end 
    set @i = @i + 1 
end 
return @n 
end 
go 

declare @str varchar(8000) 
set @str = '|' + char(9) + '|' + char(10) + '|' + char(13) 

select @str, 
    convert(float, dbo.fn_CountAscii(@str))/len(@str) as Ratio, 
    case when convert(float, dbo.fn_CountAscii(@str))/len(@str) > 0.5 then 1 else 0 end as MoreAsciiThanNonAscii 

Это может быть ужасно медленным, если набор данных велик, но сосать его и увидеть

+0

, но я имею дело с описанием поля, как следует, что положить в? – william007

+0

просто замените @str описанием, например. select description, case when convert (float, dbo.fn_CountAscii (описание))/len (description)> 0.5 then 1 else 0 end как MoreAsciiThanNonAscii из [DataExtraction]. [dbo]. [Обратная связь] –

0

Наиболее эффективный способ сделать что-то подобное, что Я могу думать о том, чтобы использовать таблицу Tally (aka Numbers). Если вы не знакомы с концепцией, вы можете прочитать об этом здесь: http://www.sqlservercentral.com/articles/T-SQL/62867/

Вы можете создать или заполнить таблицу Tally в своей базе данных (я создаю ее в своей базе данных из get-go, потому что она настолько полезна), или вы можете построить один на лету, используя CTE, но это делает больше кода, который вы должны создать. Для этого поста я буду использовать метод КТР, так что вы можете просто скопировать и вставить решение попробовать его:

DECLARE @pString VARCHAR(8000); 

SELECT @pString = 'Çüé the quick brown fox which gave me 50¢.'; 

--===== "Inline" CTE Driven "Tally Table" produces values from 0 up to 10,000... enough to cover VARCHAR(8000) 
WITH E1(N) AS (
       SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
       SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
       SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 
       ),       --10E+1 or 10 rows 
     E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows 
     E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max 
TallyCTE(N) AS (--=== This provides the "zero base" and limits the number of rows right up front 
        -- for both a performance gain and prevention of accidental "overruns" 
       SELECT 0 UNION ALL 
       SELECT TOP (DATALENGTH(ISNULL(@pString,1))) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4 
       ) 
--===== Return all t.N+1 positions and calculate the length of the element for each starting position 
SELECT ItemNumber = ROW_NUMBER() OVER(ORDER BY s.N), 
     StartPosition = s.N, 
     TheCharacter = SUBSTRING(@pString, N, 1) 
FROM TallyCTE s 
WHERE N <= LEN(@pString) 
    AND ASCII(SUBSTRING(@pString, N, 1)) > 127 

Если вы должны были сохраняться в таблице Tally ваш запрос может быть упрощенных так:

DECLARE @Parameter VARCHAR(8000); 
SET @Parameter = 'Çüé,Element01,Element02,Element03,Element04,Element05,50¢'; 

SELECT N, 
     SUBSTRING(@Parameter, N, 1) 
FROM dbo.Tally 
WHERE N <= LEN(@Parameter) 
     AND ASCII(SUBSTRING(@Parameter, N, 1)) > 127 
ORDER BY N; 

Результаты оба:

enter image description here

Смежные вопросы