2012-03-09 26 views
7

Có cách nào thông minh hơn để xóa tất cả ký tự đặc biệt thay vì có chuỗi khoảng 15 câu lệnh thay thế lồng nhau không?T-SQL bỏ tất cả các ký tự không phải là alpha và không phải là số

Các công trình sau đây, nhưng chỉ xử lý ba ký tự (dấu và, trống và dấu chấm).

select CustomerID, CustomerName, 
    Replace(Replace(Replace(CustomerName,'&',''),' ',''),'.','') as CustomerNameStripped 
from Customer 

Trả lời

14

Một cách linh hoạt-ish;

ALTER FUNCTION [dbo].[fnRemovePatternFromString](@BUFFER VARCHAR(MAX), @PATTERN VARCHAR(128)) RETURNS VARCHAR(MAX) AS 
BEGIN 
    DECLARE @POS INT = PATINDEX(@PATTERN, @BUFFER) 
    WHILE @POS > 0 BEGIN 
     SET @BUFFER = STUFF(@BUFFER, @POS, 1, '') 
     SET @POS = PATINDEX(@PATTERN, @BUFFER) 
    END 
    RETURN @BUFFER 
END 

select dbo.fnRemovePatternFromString('cake & beer $3.99!?c', '%[$&.!?]%') 

(No column name) 
cake beer 399c 
+0

Tôi thấy mọi người đang giới thiệu chức năng. \t Tôi thích ý tưởng sử dụng một hàm do người dùng định nghĩa, nhưng sau đó nó phải trải qua điều khiển thay đổi để đến môi trường sản xuất. Không có cách nào để có một chức năng trực tuyến trong truy vấn, phải không? Tôi không chắc chắn ngôn ngữ họ đang sử dụng để gọi truy vấn SQL, có thể là VBScript hoặc Powershell, nhưng bây giờ tôi nghĩ rằng nó sẽ dễ dàng hơn nhiều để thực hiện việc tước bỏ ngôn ngữ đó. – NealWalters

+0

Giống như một bảng số hoặc bảng lịch, hoặc các chức năng tách hoặc nối chuỗi, một chức năng có thể làm loại điều này là một mô-đun tiện dụng để có xung quanh. Ngay cả khi nó không đến đó ngay lập tức, bạn nên xem xét việc có những thứ này trong một cơ sở dữ liệu tiện ích. Tôi không biết rằng việc thực hiện điều này trong mã luôn luôn là câu trả lời hay nhất, đặc biệt nếu nhiều ứng dụng khác nhau cần làm điều tương tự ... –

+0

@ Alex K., tôi thích giải pháp này tốt hơn so với của riêng tôi. Tôi không bao giờ phải kiểm tra chuỗi ký tự một lần.Bạn có cách nào để thay thế các khoảng trống thừa và các ký tự đặc biệt (cr/lf, tab) không? – datagod

1

Nếu bạn có thể sử dụng SQL CLR bạn có thể sử dụng biểu thức chính quy .NET cho điều này.

Có gói bên thứ ba (miễn phí) bao gồm điều này và hơn thế nữa - SQL Sharp.

6

Tôi đã gặp sự cố này vài năm trước, vì vậy tôi đã viết một hàm SQL để thực hiện thủ thuật. Here is the original article (được sử dụng để xóa văn bản trong HTML). Tôi đã kể từ khi cập nhật các chức năng như sau:

IF (object_id('dbo.fn_CleanString') IS NOT NULL) 
BEGIN 
    PRINT 'Dropping: dbo.fn_CleanString' 
    DROP function dbo.fn_CleanString 
END 
GO 
PRINT 'Creating: dbo.fn_CleanString' 
GO 
CREATE FUNCTION dbo.fn_CleanString 
(
    @string varchar(8000) 
) 
returns varchar(8000) 
AS 
BEGIN 
--------------------------------------------------------------------------------------------------- 
-- Title:  CleanString 
-- Date Created: March 26, 2011 
-- Author:  William McEvoy 
--    
-- Description: This function removes special ascii characters from a string. 
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 


declare @char  char(1), 
     @len   int, 
     @count  int, 
     @newstring varchar(8000), 
     @replacement char(1) 

select @count  = 1, 
     @len   = 0, 
     @newstring = '', 
     @replacement = ' ' 



--------------------------------------------------------------------------------------------------- 
-- M A I N P R O C E S S I N G 
--------------------------------------------------------------------------------------------------- 


-- Remove Backspace characters 
select @string = replace(@string,char(8),@replacement) 

-- Remove Tabs 
select @string = replace(@string,char(9),@replacement) 

-- Remove line feed 
select @string = replace(@string,char(10),@replacement) 

-- Remove carriage return 
select @string = replace(@string,char(13),@replacement) 


-- Condense multiple spaces into a single space 
-- This works by changing all double spaces to be OX where O = a space, and X = a special character 
-- then all occurrences of XO are changed to O, 
-- then all occurrences of X are changed to nothing, leaving just the O which is actually a single space 
select @string = replace(replace(replace(ltrim(rtrim(@string)),' ', ' ' + char(7)),char(7)+' ',''),char(7),'') 


-- Parse each character, remove non alpha-numeric 

select @len = len(@string) 

WHILE (@count <= @len) 
BEGIN 

    -- Examine the character 
    select @char = substring(@string,@count,1) 


    IF (@char like '[a-z]') or (@char like '[A-Z]') or (@char like '[0-9]') 
    select @newstring = @newstring + @char 
    ELSE 
    select @newstring = @newstring + @replacement 

    select @count = @count + 1 

END 


return @newstring 
END 

GO 
IF (object_id('dbo.fn_CleanString') IS NOT NULL) 
    PRINT 'Function created.' 
ELSE 
    PRINT 'Function NOT created.' 
GO 
+0

Tôi thích ý tưởng sử dụng một hàm do người dùng định nghĩa, nhưng sau đó nó phải trải qua điều khiển thay đổi để đến môi trường sản xuất. – NealWalters

+0

Giải pháp tuyệt vời. – William

7

Tạo một hàm:

CREATE FUNCTION dbo.StripNonAlphaNumerics 
(
    @s VARCHAR(255) 
) 
RETURNS VARCHAR(255) 
AS 
BEGIN 
    DECLARE @p INT = 1, @n VARCHAR(255) = ''; 
    WHILE @p <= LEN(@s) 
    BEGIN 
    IF SUBSTRING(@s, @p, 1) LIKE '[A-Za-z0-9]' 
    BEGIN 
     SET @n += SUBSTRING(@s, @p, 1); 
    END 
    SET @p += 1; 
    END 
    RETURN(@n); 
END 
GO 

Sau đó:

SELECT Result = dbo.StripNonAlphaNumerics 
('My Customer''s dog & #1 friend are dope, yo!'); 

Kết quả:

Result 
------ 
MyCustomersdog1friendaredopeyo 

Để làm cho nó nhiều hơn linh hoạt, bạn có thể vượt qua trong mẫu y ou muốn cho phép:

CREATE FUNCTION dbo.StripNonAlphaNumerics 
(
    @s VARCHAR(255), 
    @pattern VARCHAR(255) 
) 
RETURNS VARCHAR(255) 
AS 
BEGIN 
    DECLARE @p INT = 1, @n VARCHAR(255) = ''; 
    WHILE @p <= LEN(@s) 
    BEGIN 
    IF SUBSTRING(@s, @p, 1) LIKE @pattern 
    BEGIN 
     SET @n += SUBSTRING(@s, @p, 1); 
    END 
    SET @p += 1; 
    END 
    RETURN(@n); 
END 
GO 

Sau đó:

SELECT r = dbo.StripNonAlphaNumerics 
('Bob''s dog & #1 friend are dope, yo!', '[A-Za-z0-9]'); 

Kết quả:

r 
------ 
Bobsdog1friendaredopeyo 
+1

@Brian xin vui lòng không chỉnh sửa mã của người khác mà không cho họ một số đầu mối về những gì "không làm việc" có nghĩa là. Nếu bạn gặp sự cố với mã, hãy để lại nhận xét, không chỉ chỉnh sửa nó. Tôi không biết tại sao bản chỉnh sửa của bạn hoạt động và bản gốc "không hoạt động" nhưng [tôi sẽ không bao giờ viết mã như thế] (http://sqlblog.com/blogs/aaron_bertrand/archive/2009/10/09/bad- thói quen-to-kick-khai báo-varchar-without-length.aspx). –

+0

Bạn đúng Aaron, nhìn lại điều này, đó là rất thô lỗ và tôi chắc chắn sẽ rất khó chịu nếu tôi là bạn. Tôi vội vã lớn và tôi xin lỗi. Vì vậy, đến thời điểm tôi đã cố gắng thực hiện mà không sử dụng các từ của tôi, @c không được xác định trong mã của bạn, do đó, điều này không chạy chút nào. Tôi nghĩ rằng tôi đã đạt được một loại cấu trúc char mà một số ngôn ngữ khác có ... Tôi chỉ cần chức năng đầu tiên nhưng phần thứ hai có lẽ cũng bị ảnh hưởng. Cảm ơn bạn đã viết mã, nó đã giúp tôi tiết kiệm thời gian. :) –

+0

Tôi thấy bạn đã sửa nó bằng cách loại bỏ @c. Cảm ơn. –

1

Tôi biết đây là một chủ đề cũ, nhưng vẫn còn, có thể có ích cho người khác. Đây là một cách nhanh chóng và dơ bẩn (Tôi đã thực hiện nghịch đảo - loại bỏ các số không) - sử dụng CTE đệ quy. Điều gì làm cho điều này trở nên tốt đẹp đối với tôi là nó là một chức năng nội tuyến - do đó, xung quanh hiệu ứng RBAR khó chịu của các hàm vô hướng và bảng có giá trị thông thường. Điều chỉnh bộ lọc của bạn theo nhu cầu để bao gồm hoặc loại trừ bất kỳ loại char nào.

 Create Function fncV1_iStripAlphasFromData (
      @iString Varchar(max) 
     ) 
     Returns 
     Table With Schemabinding 
     As 

      Return(

       with RawData as 
       (
        Select @iString as iString 
       ) 
       , 
       Anchor as 
       (

        Select Case(IsNumeric (substring(iString, 1, 1))) when 1 then substring(iString, 1, 1) else '' End as oString, 2 as CharPos from RawData 
        UNION ALL 
        Select a.oString + Case(IsNumeric (substring(@iString, a.CharPos, 1))) when 1 then substring(@iString, a.CharPos, 1) else '' End, a.CharPos + 1 
        from RawData r 
        Inner Join Anchor a on a.CharPos <= len(rtrim(ltrim(@iString))) 

       ) 

       Select top 1 oString from Anchor order by CharPos Desc 

      ) 

Go 

select * from dbo.fncV1_iStripAlphasFromData ('00000') 
select * from dbo.fncV1_iStripAlphasFromData ('00A00') 
select * from dbo.fncV1_iStripAlphasFromData ('12345ABC6789!&*0') 
Các vấn đề liên quan