2012-03-09 14 views
7

Czy istnieje inteligentniejszy sposób na usunięcie wszystkich znaków specjalnych niż z serii około 15 zagnieżdżonych instrukcji zastępowania?Pasek T-SQL dla wszystkich niealfaerycznych i nieliczbowych znaków

Następujące prace, ale obsługuje tylko trzy znaki (ampersand, puste i kropka).

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

Odpowiedz

14

Jeden elastyczny-ish sposób;

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

Widzę, że każdy poleca funkcje. \t Podoba mi się pomysł użycia funkcji zdefiniowanej przez użytkownika, ale potem musi przejść przez kontrolę zmian, aby dostać się do środowiska produkcyjnego. Nie ma możliwości, aby w zapytaniu była funkcja in-line, prawda? Nie jestem pewien, jakiego języka używają do wywoływania zapytania SQL, może VBScript lub Powershell, ale teraz myślę, że dużo łatwiej będzie zrobić stripping w tym języku. – NealWalters

+0

Podobnie jak tabelę numerów lub tabelę kalendarza lub funkcje, które dzielą lub łączą łańcuchy, funkcja, która może wykonywać tego typu rzeczy, jest przydatnym modułem do obejrzenia. Nawet jeśli nie nastąpi od razu, powinieneś rozważyć posiadanie tych rzeczy w bazie danych narzędzi. Nie wiem, czy wykonanie tego w kodzie jest zawsze najlepszą odpowiedzią, szczególnie, jeśli wiele różnych aplikacji musi zrobić to samo ... –

+0

@Alex K., Lubię to rozwiązanie lepiej niż moje własne. Nigdy nie lubiłem, gdybym badał ciąg po jednej postaci naraz.Czy masz sposób na zastąpienie dodatkowych spacji i znaków specjalnych (cr/lf, tab)? – datagod

1

Jeśli możesz użyć SQL CLR, możesz użyć do tego celu wyrażeń regularnych .NET.

Istnieje pakiet innej firmy (bezpłatny), który obejmuje to i więcej - SQL Sharp.

6

Stawiałem czoła temu problemowi kilka lat temu, więc napisałem funkcję SQL, aby załatwić sprawę. Here is the original article (został użyty do skasowania tekstu z HTML). I od tego czasu aktualizowany funkcję w następujący sposób:

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

Podoba mi się pomysł użycia funkcji zdefiniowanej przez użytkownika, ale potem musi przejść przez kontrolę zmian, aby dostać się do środowiska produkcyjnego. – NealWalters

+0

Fantastyczne rozwiązanie. – William

7

Utwórz funkcję:

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 

wówczas:

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

wyniki:

Result 
------ 
MyCustomersdog1friendaredopeyo 

Aby uczynić go bardziej elastyczny, możesz podać wzór y ou chcesz zezwolić:

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 

Następnie:

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

Wyniki:

r 
------ 
Bobsdog1friendaredopeyo 
+1

@Brian proszę nie edytować kodu innych osób, nie dając im pojęcia, co oznacza "nie działa". Jeśli masz problem z kodem, zostaw komentarz, nie edytuj go. Nie mam pojęcia, dlaczego twoja edycja zadziałała, a oryginał "nie działał", ale [nigdy bym tego nie napisał] (http://sqlblog.com/blogs/aaron_bertrand/archive/2009/10/09/bad- przyzwyczajenia do wygłaszania deklaracji-varchar-without-length.aspx). –

+0

Masz rację, Aaron, patrząc na to z góry, to było bardzo niegrzeczne i na pewno byłabym bardzo zirytowana, gdybym też był tobą. Pospieszyłem się i przepraszam. Tak więc do momentu, w którym próbowałem dokonać bez użycia moich słów, @c nie jest zdefiniowany w twoim kodzie, więc to wcale nie działa. Wydaje mi się, że sięgałem po strukturę typu char, jakiej używają inne języki ... Potrzebowałem tylko pierwszej funkcji, ale prawdopodobnie wpływ ma również druga część. Dzięki za kod, zaoszczędziło mi to trochę czasu. :) –

+0

Widzę, że naprawiłeś to, eliminując @. Dzięki. –

1

Wiem, że to stary wątek, ale nadal może być przydatny dla innych. Oto szybkie i brudne (co zrobiłem odwrotnie - usuwanie nie-numerycznych) - przy użyciu rekurencyjnego CTE. To, co sprawia mi tę przyjemność, to fakt, że jest to funkcja inline - dzięki temu można obejść paskudny efekt RBAR zwykłych funkcji skalarnych i tabelarycznych. Dostosuj filtr, aby uwzględnić lub wykluczyć dowolne typy znaków.

 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') 
Powiązane problemy