2011-12-12 20 views
9

Có cách nào để tách các ký tự đặc biệt (chỉ để lại chữ và số) từ một chuỗi/trường trong máy chủ SQL mà không có chức năng vòng lặp/tùy chỉnh không?Dải ký tự đặc biệt trong SQL không có vòng lặp?

Cho đến nay, là tốt nhất tôi đã đưa ra là:

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 

Trên một số máy chủ tôi không có đặc quyền để cread sử dụng chức năng xác định do đó, tôi muốn để có thể đạt được cùng một kết quả không có. Tôi cũng có những lo ngại về hiệu suất/hiệu suất của vòng lặp (mặc dù tôi đoán thậm chí một hàm/phương thức tích hợp có thể sẽ tự sử dụng một vòng lặp).

Cảm ơn

+1

Tôi đã soemtimes thấy đề nghị tháo dây vào một bảng như điều và tham gia vào một bảng ký tự thủ môn . [Đây là một cuộc thảo luận mà bạn có thể quan tâm] (http://ask.sqlservercentral.com/questions/75404/strip-all-but-alpha-chars-out-of-a-string) –

Trả lời

6

Tôi giả sử bạn có một cột mà bạn muốn thay thế, đây là cách bạn có thể làm điều đó:

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) 

Kết quả:

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

Nếu bạn muốn làm nhanh hơn, hãy sử dụng chức năng này.

Nếu bạn cần sử dụng nó mà không có chức năng, bạn có thể cần sử dụng con trỏ để tìm nạp từng hàng cùng một lúc và áp dụng nội dung của hàm tiếp theo cho mỗi hàng.

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

Tại sao điều này nhanh hơn? Tôi đã có thể nghĩ rằng chức năng của bạn có vòng lặp cho mỗi nhân vật của đầu vào trong khi chức năng của tôi sẽ chỉ vòng lặp cho mỗi ký tự không phải chữ số? –

+0

Bạn cũng có thể sử dụng chức năng của mình. Nhưng trong trường hợp đó bạn không nên sử dụng ''% [^ A-Za-z0-9]%'' thay vì ''% [^ a-z0-9]%''? –

0

khác vì phải một đống lớn của lồng nhau REPLACE báo cáo này là tốt nhất tôi có thể đến với. Chúng tôi có yêu cầu đa ngôn ngữ để tước thứ trở lại Alpha-số không hoạt động cho các ngôn ngữ như tiếng Ả Rập

người
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 
Các vấn đề liên quan