2011-12-12 17 views
9

Czy istnieje sposób na usunięcie znaków specjalnych (pozostawiając jedynie alfanumeryczne) z ciągu znaków/pola w serwerze SQL bez funkcji pętli/niestandardowej?Usunąć znaki specjalne w języku SQL bez pętli?

Jak dotąd, najlepsze, jakie wymyślić to:

Create Function [dbo].[strip_special](@Temp VarChar(1000)) 
Returns VarChar(1000) 
AS 
Begin 
    While PatIndex('%[^a-z0-9]%', @Temp) > 0 
     Set @Temp = Stuff(@Temp, PatIndex('%[^a-z0-9]%', @Temp), 1, '') 
    Return @TEmp 
End 

Na niektórych serwerach nie mam uprawnień do cread zdefiniowane przez użytkownika funkcje, więc chciałbym, aby móc osiągnąć ten sam wynik bez. Mam również obawy dotyczące wydajności/wydajności pętli (chociaż domyślam się, że nawet wbudowana funkcja/metoda prawdopodobnie używa pętli).

Dzięki

+1

Mam soemtimes widziane osoby sugerują demontażu strun do stołu jak rzeczy i dołączeniem do tabeli znaków Ustalacz . [Oto dyskusja, którą możesz być zainteresowany] (http://ask.sqlservercentral.com/questions/75404/strip-all- but-alpha-chars-out-of-a-string) –

Odpowiedz

6

Zakładam, że masz kolumnę, którą chcesz wymienić, to w jaki sposób można to zrobić:

declare @table table(id int, temp varchar(15)) 


insert @table values(1, 'abc-.123+') 
insert @table values(2, '¤%&(abc-.?=&(/#') 

;with t1 as 
(
select temp a, id from @table 
union all 
select cast(replace(a, substring(a, PatIndex('%[^a-z0-9]%', a), 1), '') as varchar(15)), id 
from t1 
where PatIndex('%[^a-z0-9]%', a) > 0 
) 
select t2.*, t1.a from t1 
join @table t2 
on t1.id = t2.id 
where PatIndex('%[^a-z0-9]%', a) = 0 
option (maxrecursion 0) 

Wynik:

id   temp   a 
----------- --------------- --------------- 
2   ¤%&(abc-.?=&(/# abc 
1   abc-.123+  abc123 
1

Jeśli chcesz zrobić to szybciej, użyj tej funkcji.

Jeśli musisz używać go bez funkcji, możesz potrzebować używać kursorów do pobierania każdego wiersza na raz i stosowania zawartości następnej funkcji dla każdego wiersza.

create function dbo.strip_special(@s varchar(256)) returns varchar(256) 
    with schemabinding 
begin 
    if @s is null 
     return null 
    declare @s2 varchar(256) 
    set @s2 = '' 
    declare @l int 
    set @l = len(@s) 
    declare @p int 
    set @p = 1 
    while @p <= @l begin 
     declare @c int 
     set @c = ascii(substring(@s, @p, 1)) 
     if @c between 48 and 57 or @c between 65 and 90 or @c between 97 and 122 
     set @s2 = @s2 + char(@c) 
     set @p = @p + 1 
     end 
    if len(@s2) = 0 
     return null 
    return @s2 

    end 
+3

Dlaczego jest to szybsze? Myślałbym, że twoja funkcja musi zapętlać się dla każdego znaku wejściowego, podczas gdy moja funkcja będzie pętla dla każdego znaku niealfanumerycznego? –

+0

Możesz również użyć swojej funkcji. Ale w takim przypadku nie powinieneś używać ''% [^ A-Za-z0-9]%'' zamiast '% [^ a-z0-9]% ''? –

0

Inne niż o wielki stos zagnieżdżone REPLACE statement to najlepsze, co mogłem wymyślić. Mamy wielojęzyczne wymóg tak odpędzania rzeczy z powrotem do alfanumerycznego nie działa dla języków takich jak arabski

DECLARE 
    @OrgString nVarchar(max), 
    @Pattern nvarchar(max) 


SET @OrgString = N'~,`,!,@,#,$,%,^,&,*,(,),0-9,_,-,+,=,[,],{,},;,:,",<,>,?,/,\,|حساب "خارج الميز1$انية"' 
SET @Pattern = '%[~,`,!,@,#,$,%,^,&,*,(,),0-9,_,''-,+,=,[,{,},;,:,",<,>,?,/,\,|]%' 


WHILE PATINDEX(@Pattern, @OrgString) > 0 
    SET @OrgString = REPLACE(@OrgString, SUBSTRING(@OrgString, PATINDEX(@Pattern, @OrgString), 1), '') 
SELECT REPLACE(@OrgString, ']', '') -- Cant workout how to put ] in @Pattern