Cómo quitar todos los caracteres no alfabéticos de la cadena en SQL Server?

¿Cómo podría eliminar todos los caracteres que no son alfabéticos de una cadena?

¿Qué hay de los no alfanuméricos?

¿Tiene que ser una función personalizada o hay también soluciones más generalizables?

Prueba esta función:

Create Function [dbo].[RemoveNonAlphaCharacters](@Temp VarChar(1000)) Returns VarChar(1000) AS Begin Declare @KeepValues as varchar(50) Set @KeepValues = '%[^az]%' While PatIndex(@KeepValues, @Temp) > 0 Set @Temp = Stuff(@Temp, PatIndex(@KeepValues, @Temp), 1, '') Return @Temp End 

Llámalo así:

 Select dbo.RemoveNonAlphaCharacters('abc1234def5678ghi90jkl') 

Una vez que comprenda el código, debería ver que es relativamente simple cambiarlo para eliminar otros caracteres también. Incluso podría hacer esto lo suficientemente dynamic como para pasar en su patrón de búsqueda.

Espero eso ayude.

Versión parametrizada de la increíble respuesta de G Mastros :

 CREATE FUNCTION [dbo].[fn_StripCharacters] ( @String NVARCHAR(MAX), @MatchExpression VARCHAR(255) ) RETURNS NVARCHAR(MAX) AS BEGIN SET @MatchExpression = '%['+@MatchExpression+']%' WHILE PatIndex(@MatchExpression, @String) > 0 SET @String = Stuff(@String, PatIndex(@MatchExpression, @String), 1, '') RETURN @String END 

Alfabético solamente:

 SELECT dbo.fn_StripCharacters('a1!s2@d3#f4$', '^a-z') 

Solo numérico:

 SELECT dbo.fn_StripCharacters('a1!s2@d3#f4$', '^0-9') 

Alfanumérico solamente:

 SELECT dbo.fn_StripCharacters('a1!s2@d3#f4$', '^a-z0-9') 

No alfanumérico:

 SELECT dbo.fn_StripCharacters('a1!s2@d3#f4$', 'a-z0-9') 

Sabía que SQL era malo en la manipulación de cadenas, pero no pensé que sería tan difícil. Aquí hay una función simple para eliminar todos los números de una cadena. Habría mejores formas de hacerlo, pero esto es un comienzo.

 CREATE FUNCTION dbo.AlphaOnly ( @String varchar(100) ) RETURNS varchar(100) AS BEGIN RETURN ( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( @String, '9', ''), '8', ''), '7', ''), '6', ''), '5', ''), '4', ''), '3', ''), '2', ''), '1', ''), '0', '') ) END GO -- ================== DECLARE @t TABLE ( ColID int, ColString varchar(50) ) INSERT INTO @t VALUES (1, 'abc1234567890') SELECT ColID, ColString, dbo.AlphaOnly(ColString) FROM @t 

Salida

 ColID ColString ----- ------------- --- 1 abc1234567890 abc 

Ronda 2: lista negra basada en datos

 -- ============================================ -- Create a table of blacklist characters -- ============================================ IF EXISTS (SELECT * FROM sys.tables WHERE [object_id] = OBJECT_ID('dbo.CharacterBlacklist')) DROP TABLE dbo.CharacterBlacklist GO CREATE TABLE dbo.CharacterBlacklist ( CharID int IDENTITY, DisallowedCharacter nchar(1) NOT NULL ) GO INSERT INTO dbo.CharacterBlacklist (DisallowedCharacter) VALUES (N'0') INSERT INTO dbo.CharacterBlacklist (DisallowedCharacter) VALUES (N'1') INSERT INTO dbo.CharacterBlacklist (DisallowedCharacter) VALUES (N'2') INSERT INTO dbo.CharacterBlacklist (DisallowedCharacter) VALUES (N'3') INSERT INTO dbo.CharacterBlacklist (DisallowedCharacter) VALUES (N'4') INSERT INTO dbo.CharacterBlacklist (DisallowedCharacter) VALUES (N'5') INSERT INTO dbo.CharacterBlacklist (DisallowedCharacter) VALUES (N'6') INSERT INTO dbo.CharacterBlacklist (DisallowedCharacter) VALUES (N'7') INSERT INTO dbo.CharacterBlacklist (DisallowedCharacter) VALUES (N'8') INSERT INTO dbo.CharacterBlacklist (DisallowedCharacter) VALUES (N'9') GO -- ==================================== IF EXISTS (SELECT * FROM sys.objects WHERE [object_id] = OBJECT_ID('dbo.StripBlacklistCharacters')) DROP FUNCTION dbo.StripBlacklistCharacters GO CREATE FUNCTION dbo.StripBlacklistCharacters ( @String nvarchar(100) ) RETURNS varchar(100) AS BEGIN DECLARE @blacklistCt int DECLARE @ct int DECLARE @c nchar(1) SELECT @blacklistCt = COUNT(*) FROM dbo.CharacterBlacklist SET @ct = 0 WHILE @ct < @blacklistCt BEGIN SET @ct = @ct + 1 SELECT @String = REPLACE(@String, DisallowedCharacter, N'') FROM dbo.CharacterBlacklist WHERE CharID = @ct END RETURN (@String) END GO -- ==================================== DECLARE @s nvarchar(24) SET @s = N'abc1234def5678ghi90jkl' SELECT @s AS OriginalString, dbo.StripBlacklistCharacters(@s) AS ResultString 

Salida

 OriginalString ResultString ------------------------ ------------ abc1234def5678ghi90jkl abcdefghijkl 

Mi desafío para los lectores: ¿Puedes hacer esto más eficiente? ¿Qué hay de usar recursión?

Si eres como yo y no tienes acceso a solo agregar funciones a tus datos de producción, pero aún deseas realizar este tipo de filtrado, aquí hay una solución SQL pura que usa una tabla PIVOT para volver a unir las piezas filtradas.

NB He codificado la tabla con hasta 40 caracteres, tendrás que agregar más si tienes cadenas más largas para filtrar.

 SET CONCAT_NULL_YIELDS_NULL OFF; with ToBeScrubbed as ( select 1 as id, '*SOME 222@ !@* #* BOGUS !@*&! DATA' as ColumnToScrub ), Scrubbed as ( select P.Number as ValueOrder, isnull ( substring ( t.ColumnToScrub , number , 1 ) , '' ) as ScrubbedValue, t.id from ToBeScrubbed t left join master..spt_values P on P.number between 1 and len(t.ColumnToScrub) and type ='P' where PatIndex('%[^az]%', substring(t.ColumnToScrub,P.number,1) ) = 0 ) SELECT id, [1]+ [2]+ [3]+ [4]+ [5]+ [6]+ [7]+ [8] +[9] +[10] + [11]+ [12]+ [13]+ [14]+ [15]+ [16]+ [17]+ [18] +[19] +[20] + [21]+ [22]+ [23]+ [24]+ [25]+ [26]+ [27]+ [28] +[29] +[30] + [31]+ [32]+ [33]+ [34]+ [35]+ [36]+ [37]+ [38] +[39] +[40] as ScrubbedData FROM ( select * from Scrubbed ) src PIVOT ( MAX(ScrubbedValue) FOR ValueOrder IN ( [1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12], [13], [14], [15], [16], [17], [18], [19], [20], [21], [22], [23], [24], [25], [26], [27], [28], [29], [30], [31], [32], [33], [34], [35], [36], [37], [38], [39], [40] ) ) pvt 

Después de haber analizado todas las soluciones dadas, pensé que tenía que haber un método SQL puro que no requiriera una función o una consulta CTE / XML, y que no implique el mantenimiento de declaraciones REEMPLAZADAS anidadas. Aquí está mi solución:

 SELECT x ,CASE WHEN a NOT LIKE '%' + SUBSTRING(x, 1, 1) + '%' THEN '' ELSE SUBSTRING(x, 1, 1) END + CASE WHEN a NOT LIKE '%' + SUBSTRING(x, 2, 1) + '%' THEN '' ELSE SUBSTRING(x, 2, 1) END + CASE WHEN a NOT LIKE '%' + SUBSTRING(x, 3, 1) + '%' THEN '' ELSE SUBSTRING(x, 3, 1) END + CASE WHEN a NOT LIKE '%' + SUBSTRING(x, 4, 1) + '%' THEN '' ELSE SUBSTRING(x, 4, 1) END + CASE WHEN a NOT LIKE '%' + SUBSTRING(x, 5, 1) + '%' THEN '' ELSE SUBSTRING(x, 5, 1) END + CASE WHEN a NOT LIKE '%' + SUBSTRING(x, 6, 1) + '%' THEN '' ELSE SUBSTRING(x, 6, 1) END -- Keep adding rows until you reach the column size AS stripped_column FROM (SELECT column_to_strip AS x ,'ABCDEFGHIJKLMNOPQRSTUVWXYZ' AS a FROM my_table) a 

La ventaja de hacerlo de esta manera es que los caracteres válidos están contenidos en una cadena en la consulta secundaria, lo que facilita su reconfiguración para un conjunto diferente de caracteres.

La desventaja es que debe agregar una fila de SQL para cada personaje hasta el tamaño de su columna. Para facilitar esa tarea, acabo de utilizar el script de Powershell a continuación, este ejemplo si es VARCHAR (64):

 1..64 | % { " + CASE WHEN a NOT LIKE '%' + SUBSTRING(x, {0}, 1) + '%' THEN '' ELSE SUBSTRING(x, {0}, 1) END" -f $_ } | clip.exe 

Lo creas o no, en mi sistema esta fea función funciona mejor que la elegante de G Mastros.

 CREATE FUNCTION dbo.RemoveSpecialChar (@s VARCHAR(256)) RETURNS VARCHAR(256) WITH SCHEMABINDING BEGIN IF @s IS NULL RETURN NULL DECLARE @s2 VARCHAR(256) = '', @l INT = LEN(@s), @p INT = 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 

Esta es una forma muy torpe de tomar todos los personajes que no quieres. El problema es que debe especificar qué caracteres no quiere. Si ingresa un nuevo personaje, lo obtendrá a menos que lo agregue a la lista.

Lo bueno es que no tienes que crear una función especial. No tengo permisos de escritura, así que esto me permite ejecutar desde una consulta simple.

 REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE( REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE( REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE( REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE( REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE( p.Name ,'®','') ,'©','') ,'ö','o') ,'ë','e') ,'ä','a') ,'ü','u') ,'ú','u') ,'í','i') ,'ï','i') ,'™','') ,'é','e') ,'²','2') ,'è','e') ,'—','-') ,'–','-') ,'ó','o') ,'•',' ') ,'…','.') ,'ô','o') ,'â','a') ,'á','a') ,'ê','e') ,'è','e') ,''',' ') ,'·',' ') ,'à','a') ,'å','a') ,'ã','a') ,'’',' ') ,'a€s','as') ,'ø','o') ,'ñ','n') ,'î','i') ,'ç','c') ,'Ç','C') ,'Ã','A') ,'”','"') ,'“','"') ,'Á','A') ,'¢','c') ,'Ã','A') ,'Å','A') ,'¶','S') ,'×','x') ,'†','') ,'š','') ,'¤','') ,'µ','') ,'õ','') ,'€','') ,''','') ,'Õ','') ,'ð','') ,'Ò','') ,'¨','') ,'º','') ,'°','') ,'ì','') ,'ƒ','') ,'ÿ','') ,'ß','') ,'«','') ,'»','') ,'Æ','') ,'¬','') ,'Ù','') ,'ý','') ,'û','') ,'|','') as Name 

Esta solución, inspirada en la solución del Sr. Allen, requiere una tabla de números enteros (que debe tener a mano si desea realizar operaciones de consulta serias con buen rendimiento). No requiere un CTE. Puede cambiar la expresión NOT IN (...) para excluir caracteres específicos, o cambiarla a una expresión IN (...) OR LIKE para retener solo ciertos caracteres.

 SELECT ( SELECT SUBSTRING([YourString], N, 1) FROM dbo.Numbers WHERE N > 0 AND N <= CONVERT(INT, LEN([YourString])) AND SUBSTRING([YourString], N, 1) NOT IN ('(',')',',','.') FOR XML PATH('') ) AS [YourStringTransformed] FROM ... 

Aquí hay una solución que no requiere la creación de una función o una lista de todas las instancias de personajes para reemplazar. Utiliza una instrucción WITH recursiva en combinación con un PATINDEX para encontrar caracteres no deseados. Reemplazará todos los caracteres no deseados en una columna: hasta 100 caracteres malos únicos contenidos en una cadena determinada. (Por ejemplo, “ABC123DEF234” contendría 4 caracteres malos 1, 2, 3 y 4). El límite 100 es la cantidad máxima de recurrencias permitidas en una statement WITH, pero esto no impone un límite en el número de filas a procesar, lo cual solo está limitado por la memoria disponible.
Si no desea resultados DISTINCT, puede eliminar las dos opciones del código.

 -- Create some test data: SELECT * INTO #testData FROM (VALUES ('ABC DEF,Kl(p)'),('123H,J,234'),('ABCD EFG')) as t(TXT) -- Actual query: -- Remove non-alpha chars: '%[^AZ]%' -- Remove non-alphanumeric chars: '%[^A-Z0-9]%' DECLARE @BadCharacterPattern VARCHAR(250) = '%[^AZ]%'; WITH recurMain as ( SELECT DISTINCT CAST(TXT AS VARCHAR(250)) AS TXT, PATINDEX(@BadCharacterPattern, TXT) AS BadCharIndex FROM #testData UNION ALL SELECT CAST(TXT AS VARCHAR(250)) AS TXT, PATINDEX(@BadCharacterPattern, TXT) AS BadCharIndex FROM ( SELECT CASE WHEN BadCharIndex > 0 THEN REPLACE(TXT, SUBSTRING(TXT, BadCharIndex, 1), '') ELSE TXT END AS TXT FROM recurMain WHERE BadCharIndex > 0 ) badCharFinder ) SELECT DISTINCT TXT FROM recurMain WHERE BadCharIndex = 0; 

Aquí hay otra forma de eliminar caracteres no alfabéticos utilizando un iTVF . En primer lugar, necesita un divisor de cadenas basado en patrones. Aquí hay una tomada del artículo de Dwain Camp:

 -- PatternSplitCM will split a string based on a pattern of the form -- supported by LIKE and PATINDEX -- -- Created by: Chris Morris 12-Oct-2012 CREATE FUNCTION [dbo].[PatternSplitCM] ( @List VARCHAR(8000) = NULL ,@Pattern VARCHAR(50) ) RETURNS TABLE WITH SCHEMABINDING AS RETURN WITH numbers AS ( SELECT TOP(ISNULL(DATALENGTH(@List), 0)) n = ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) FROM (VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) d (n), (VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) e (n), (VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) f (n), (VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) g (n) ) SELECT ItemNumber = ROW_NUMBER() OVER(ORDER BY MIN(n)), Item = SUBSTRING(@List,MIN(n),1+MAX(n)-MIN(n)), [Matched] FROM ( SELECT n, y.[Matched], Grouper = n - ROW_NUMBER() OVER(ORDER BY y.[Matched],n) FROM numbers CROSS APPLY ( SELECT [Matched] = CASE WHEN SUBSTRING(@List,n,1) LIKE @Pattern THEN 1 ELSE 0 END ) y ) d GROUP BY [Matched], Grouper 

Ahora que tiene un divisor basado en patrones, necesita dividir las cadenas que coinciden con el patrón:

 [az] 

y luego concatenarlos para obtener el resultado deseado:

 SELECT * FROM tbl t CROSS APPLY( SELECT Item + '' FROM dbo.PatternSplitCM(t.str, '[az]') WHERE Matched = 1 ORDER BY ItemNumber FOR XML PATH('') ) x (a) 

MUESTRA

Resultado:

 | Id | str | a | |----|------------------|----------------| | 1 | test“te d'abc | testtedabc | | 2 | anr¤a | anra | | 3 | gs-re-C“te d'ab | gsreCtedab | | 4 | M‚fe, DF | MfeDF | | 5 | R™temd | Rtemd | | 6 | ™jad”ji | jadji | | 7 | Cje y ret¢n | Cjeyretn | | 8 | J™kl™balu | Jklbalu | | 9 | le“ne-iokd | leneiokd | | 10 | liode-Pyr‚n‚ie | liodePyrnie | | 11 | V„s G”ta | VsGta | | 12 | Sƒo Paulo | SoPaulo | | 13 | vAstra gAtaland | vAstragAtaland | | 14 | ¥uble / Bio-Bio | ubleBioBio | | 15 | U“pl™n/ds VAsb-y | UplndsVAsby | 

Puse esto en ambos lugares donde se llama a PatIndex.

 PatIndex('%[^A-Za-z0-9]%', @Temp) 

para la función personalizada anterior RemoveNonAlphaCharacters y la renombré RemoveNonAlphaNumericCharacters

–Primero crea una función

 CREATE FUNCTION [dbo].[GetNumericonly] (@strAlphaNumeric VARCHAR(256)) RETURNS VARCHAR(256) AS BEGIN DECLARE @intAlpha INT SET @intAlpha = PATINDEX('%[^0-9]%', @strAlphaNumeric) BEGIN WHILE @intAlpha > 0 BEGIN SET @strAlphaNumeric = STUFF(@strAlphaNumeric, @intAlpha, 1, '' ) SET @intAlpha = PATINDEX('%[^0-9]%', @strAlphaNumeric ) END END RETURN ISNULL(@strAlphaNumeric,0) END 

Ahora llama a esta función como

 select [dbo].[GetNumericonly]('Abhi12shek23jaiswal') 

Su resultado como

 1223 

Desde la perspectiva del rendimiento, usaría la función en línea:

 SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE FUNCTION [dbo].[udf_RemoveNumericCharsFromString] ( @List NVARCHAR(4000) ) RETURNS TABLE AS RETURN WITH GetNums AS ( SELECT TOP(ISNULL(DATALENGTH(@List), 0)) n = ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) FROM (VALUES (0),(0),(0),(0)) d (n), (VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) e (n), (VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) f (n), (VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) g (n) ) SELECT StrOut = ''+ (SELECT Chr FROM GetNums CROSS APPLY (SELECT SUBSTRING(@List , n,1)) X(Chr) WHERE Chr LIKE '%[^0-9]%' ORDER BY N FOR XML PATH (''),TYPE).value('.','NVARCHAR(MAX)') /*How to Use SELECT StrOut FROM dbo.udf_RemoveNumericCharsFromString ('vv45--9gut') Result: vv--gut */ 

Utilizando una tabla de números generada por CTE para examinar cada carácter, luego para que XML se una a una cadena de valores guardados, puede …

 CREATE FUNCTION [dbo].[PatRemove]( @pattern varchar(50), @expression varchar(8000) ) RETURNS varchar(8000) AS BEGIN WITH d(d) AS (SELECT d FROM (VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) digits(d)), nums(n) AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM d d1, d d2, d d3, d d4), chars(c) AS (SELECT SUBSTRING(@expression, n, 1) FROM nums WHERE n <= LEN(@expression)) SELECT @expression = (SELECT c AS [text()] FROM chars WHERE c NOT LIKE @pattern FOR XML PATH('')); RETURN @expression; END 
 DECLARE @vchVAlue NVARCHAR(255) = 'SWP, Lettering Position 1: 4 Ω, 2: 8 Ω, 3: 16 Ω, 4: , 5: , 6: , Voltage Selector, Solder, 6, Step switch, : w/o fuseholder ' WHILE PATINDEX('%?%' , CAST(@vchVAlue AS VARCHAR(255))) > 0 BEGIN SELECT @vchVAlue = STUFF(@vchVAlue,PATINDEX('%?%' , CAST(@vchVAlue AS VARCHAR(255))),1,' ') END SELECT @vchVAlue 

De esta manera no funcionó para mí, ya que estaba tratando de mantener las letras en árabe intenté reemplazar la expresión regular, pero tampoco funcionó. Escribí otro método para trabajar en el nivel ASCII ya que era mi única opción y funcionó.

  Create function [dbo].[RemoveNonAlphaCharacters] (@s varchar(4000)) returns varchar(4000) with schemabinding begin if @s is null return null declare @s2 varchar(4000) 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 or @c between 165 and 253 or @c between 32 and 33 set @s2 = @s2 + char(@c) set @p = @p + 1 end if len(@s2) = 0 return null return @s2 end 

IR

Aquí hay otra solución CTE recursiva, basada en la respuesta de @Gerhard Weiss aquí . Debería poder copiar y pegar todo el bloque de código en SSMS y jugar allí. Los resultados incluyen algunas columnas adicionales para ayudarnos a entender qué está pasando. Me tomó un tiempo hasta que entendí todo lo que está pasando con PATINDEX (RegEx) y el CTE recursivo.

 DECLARE @DefineBadCharPattern varchar(30) SET @DefineBadCharPattern = '%[^Az]%' --Means anything NOT between A and z characters (according to ascii char value) is "bad" SET @DefineBadCharPattern = '%[^a-z0-9]%' --Means anything NOT between a and z characters or numbers 0 through 9 (according to ascii char value) are "bad" SET @DefineBadCharPattern = '%[^ -~]%' --Means anything NOT between space and ~ characters (all non-printable characters) is "bad" --Change @ReplaceBadCharWith to '' to strip "bad" characters from string --Change to some character if you want to 'see' what's being replaced. NOTE: It must be allowed accoring to @DefineBadCharPattern above DECLARE @ReplaceBadCharWith varchar(1) = '#' --Change this to whatever you want to replace non-printable chars with IF patindex(@DefineBadCharPattern COLLATE Latin1_General_BIN, @ReplaceBadCharWith) > 0 BEGIN RAISERROR('@ReplaceBadCharWith value (%s) must be a character allowed by PATINDEX pattern of %s',16,1,@ReplaceBadCharWith, @DefineBadCharPattern) RETURN END --A table of values to play with: DECLARE @temp TABLE (OriginalString varchar(100)) INSERT @temp SELECT ' 1hello' + char(13) + char(10) + 'there' + char(30) + char(9) + char(13) + char(10) INSERT @temp SELECT '2hello' + char(30) + 'there' + char(30) INSERT @temp SELECT ' 3hello there' INSERT @temp SELECT ' tab' + char(9) + ' character' INSERT @temp SELECT 'good bye' --Let the magic begin: ;WITH recurse AS ( select OriginalString, OriginalString as CleanString, patindex(@DefineBadCharPattern COLLATE Latin1_General_BIN, OriginalString) as [Position], substring(OriginalString,patindex(@DefineBadCharPattern COLLATE Latin1_General_BIN, OriginalString),1) as [InvalidCharacter], ascii(substring(OriginalString,patindex(@DefineBadCharPattern COLLATE Latin1_General_BIN, OriginalString),1)) as [ASCIICode] from @temp UNION ALL select OriginalString, CONVERT(varchar(100),REPLACE(CleanString,InvalidCharacter,@ReplaceBadCharWith)), patindex(@DefineBadCharPattern COLLATE Latin1_General_BIN,CleanString) as [Position], substring(CleanString,patindex(@DefineBadCharPattern COLLATE Latin1_General_BIN,CleanString),1), ascii(substring(CleanString,patindex(@DefineBadCharPattern COLLATE Latin1_General_BIN,CleanString),1)) from recurse where patindex(@DefineBadCharPattern COLLATE Latin1_General_BIN,CleanString) > 0 ) SELECT * FROM recurse --optionally comment out this last WHERE clause to see more of what the recursion is doing: WHERE patindex(@DefineBadCharPattern COLLATE Latin1_General_BIN,CleanString) = 0 

Aunque la publicación es un poco antigua, me gustaría decir lo siguiente. El problema que tuve con la solución anterior es que no filtra caracteres como ç, ë, ï, etc. Adapte una función de la siguiente manera (solo usé una cadena de varchar de 80 para ahorrar memoria):

 create FUNCTION dbo.udf_Cleanchars (@InputString varchar(80)) RETURNS varchar(80) AS BEGIN declare @return varchar(80) , @length int , @counter int , @cur_char char(1) SET @return = '' SET @length = 0 SET @counter = 1 SET @length = LEN(@InputString) IF @length > 0 BEGIN WHILE @counter <= @length BEGIN SET @cur_char = SUBSTRING(@InputString, @counter, 1) IF ((ascii(@cur_char) in (32,44,46)) or (ascii(@cur_char) between 48 and 57) or (ascii(@cur_char) between 65 and 90) or (ascii(@cur_char) between 97 and 122)) BEGIN SET @return = @return + @cur_char END SET @counter = @counter + 1 END END RETURN @return END 

Acabo de encontrar esto integrado en Oracle 10g si eso es lo que estás usando. Tuve que quitar todos los caracteres especiales para comparar un número de teléfono.

 regexp_replace(c.phone, '[^0-9]', '') 
    Intereting Posts