Reemplazar espacios duplicados con un solo espacio en T-SQL


100

Necesito asegurarme de que un campo determinado no tenga más de un espacio (no me preocupan todos los espacios en blanco, solo el espacio) entre caracteres.

Entonces

'single    spaces   only'

necesita ser convertido en

'single spaces only'

Lo siguiente no funcionará

select replace('single    spaces   only','  ',' ')

ya que resultaría en

'single  spaces  only'

Realmente preferiría seguir con T-SQL nativo en lugar de una solución basada en CLR.

Pensamientos


Puede hacer esto con un reemplazo de REGEX
Raj More

Respuestas:


325

Aún más ordenado:

select string = replace(replace(replace(' select   single       spaces',' ','<>'),'><',''),'<>',' ')

Salida:

seleccionar espacios individuales


6
Si desea eliminar los espacios al frente y al final de la cadena, envuelva el reemplazo en un LTRIM, RTRIM y lo hará por usted.
Neil Knight

5
Siempre que su cadena no contenga muchos signos <o>. Parece frágil para mi gusto.
JohnFx

8
Truco verdaderamente elegante. Voto a favor. Se pueden usar dos caracteres cualesquiera para la parte central si <> están potencialmente en el texto de entrada.
richardtallent

32
Chris, puede usar caracteres ASCII no imprimibles como CHAR (17) y CHAR (18), ya que NUNCA estarán en su texto de entrada. Aún más rápido que el bucle de la respuesta aceptada.
richardtallent

7
Realmente tuve que mirar esto por un momento para descubrir que usaste '> <', '' Sin reemplazo de espacio, pero ahora que lo entiendo ... es muy brillante. Me gustó mucho la sugerencia de @richardtallent de usar los caracteres ASCII no imprimibles cuya combinación agregada produce: REPLACE (REPLACE (REPLACE (LastName, '', 'CHAR (17) CHAR (18)'), 'CHAR (18 ) CHAR (17) ',' '),' CHAR (17) CHAR (18) ',' ')
Anthony Griggs

25

Esto funcionaría:

declare @test varchar(100)
set @test = 'this   is  a    test'

while charindex('  ',@test  ) > 0
begin
   set @test = replace(@test, '  ', ' ')
end

select @test

1
Envolviendo la función y cambiando varchar (100) a nvarchar (max)
Christoph

La diferencia entre los scripts de James y Neil es que James se ejecuta en un bucle while que, en la experiencia personal, hacer que se ejecute a través de 50.000 registros de una tabla tiende a ser muy lento, por lo que debe crearlo como un procedimiento y pasar un registro y algunos Es posible que no tenga permiso para crear un nuevo procedimiento de banda. Usos de Neil per-existente funciones, ya que utiliza <>, si usted tiene una cadena como "release < now"entonces obtendrá "release<><><<><>now", "release<<>now", "release< now", es el mismo con cualquier par de símbolos, si usted tiene un solo uno de los dos entonces va a mover
Memor-X

1
ejecutar esto a través de 50k registros debería ser muy rápido, buscaría otros problemas si ese es su problema.
user3486773

17

Si sabe que no habrá más de un cierto número de espacios en una fila, puede simplemente anidar el reemplazo:

replace(replace(replace(replace(myText,'  ',' '),'  ',' '),'  ',' '),'  ',' ')

4 reemplazos deben fijar hasta 16 espacios consecutivos (16, luego 8, luego 4, luego 2, luego 1)

Si pudiera ser significativamente más largo, entonces tendría que hacer algo como una función en línea:

CREATE FUNCTION strip_spaces(@str varchar(8000))
RETURNS varchar(8000) AS
BEGIN 
    WHILE CHARINDEX('  ', @str) > 0 
        SET @str = REPLACE(@str, '  ', ' ')

    RETURN @str
END

Entonces solo hazlo

SELECT dbo.strip_spaces(myText) FROM myTable

Brad, tenía un código casi idéntico pero me ganaste en el Post, así que vota a favor. Varias llamadas REPLACE () son pirateadas, pero si el número de espacios "extra" esperados es predecible y relativamente pequeño, funcionará bien y cumplirá con el requisito del OP de no llamar al código RegEx a través del CLR.
richardtallent

6
update mytable
set myfield = replace (myfield, '  ',  ' ')
where charindex('  ', myfield) > 0 

Reemplazar funcionará en todos los espacios dobles, no es necesario colocar múltiples reemplazos. Esta es la solución basada en conjuntos.


¿No colapsaría esto 4 espacios en 2?
Christoph

Llamé a esta solución en mis preguntas porque no satisface la necesidad, pero gracias.
Christoph

6

Se puede hacer de forma recursiva a través de la función:

CREATE FUNCTION dbo.RemSpaceFromStr(@str VARCHAR(MAX)) RETURNS VARCHAR(MAX) AS
BEGIN
  RETURN (CASE WHEN CHARINDEX('  ', @str) > 0 THEN
    dbo.RemSpaceFromStr(REPLACE(@str, '  ', ' ')) ELSE @str END);
END

entonces, por ejemplo:

SELECT dbo.RemSpaceFromStr('some   string    with         many     spaces') AS NewStr

devoluciones:

NewStr
some string with many spaces

O la solución basada en el método descrito por @ agdk26 o @Neil Knight (pero más seguro)
ambos ejemplos devuelven el resultado anterior:

SELECT REPLACE(REPLACE(REPLACE('some   string    with         many     spaces'
  , '  ', ' ' + CHAR(7)), CHAR(7) + ' ', ''), ' ' + CHAR(7), ' ') AS NewStr 
--but it remove CHAR(7) (Bell) from string if exists...

o

SELECT REPLACE(REPLACE(REPLACE('some   string    with         many     spaces'
  , '  ', ' ' + CHAR(7) + CHAR(7)), CHAR(7) + CHAR(7) + ' ', ''), ' ' + CHAR(7) + CHAR(7), ' ') AS NewStr
--but it remove CHAR(7) + CHAR(7) from string

Cómo funciona: ingrese la descripción de la imagen aquí

Precaución: El carácter
/ cadena utilizado para reemplazar espacios no debe existir al principio o al final de la cadena y ser independiente.


1
Me gusta la idea de una función recursiva para esto. ¿Hay algo de lo que deba estar consciente?
Zach Smith

5

Esto es algo de fuerza bruta, pero funcionará

CREATE FUNCTION stripDoubleSpaces(@prmSource varchar(max)) Returns varchar(max)
AS 
BEGIN
    WHILE (PATINDEX('%  %', @prmSource)>0)
     BEGIN
        SET @prmSource = replace(@prmSource  ,'  ',' ')
     END

    RETURN @prmSource
END

GO

-- Unit test -- 
PRINT dbo.stripDoubleSpaces('single    spaces   only')

single spaces only

2

Aquí hay una función simple que creé para limpiar cualquier espacio antes o después, y múltiples espacios dentro de una cadena. Maneja con gracia hasta 108 espacios en un solo tramo y tantos bloques como haya en la cuerda. Puede aumentar eso en factores de 8 agregando líneas adicionales con espacios más grandes si es necesario. Parece funcionar rápidamente y no ha causado ningún problema a pesar de su uso generalizado en una gran aplicación.

CREATE FUNCTION [dbo].[fnReplaceMultipleSpaces] (@StrVal AS VARCHAR(4000)) 
RETURNS VARCHAR(4000) 
AS 
BEGIN

    SET @StrVal = Ltrim(@StrVal)
    SET @StrVal = Rtrim(@StrVal)

    SET @StrVal = REPLACE(@StrVal, '                ', ' ')  -- 16 spaces
    SET @StrVal = REPLACE(@StrVal, '        ', ' ')  -- 8 spaces
    SET @StrVal = REPLACE(@StrVal, '    ', ' ')  -- 4 spaces
    SET @StrVal = REPLACE(@StrVal, '  ', ' ')  -- 2 spaces
    SET @StrVal = REPLACE(@StrVal, '  ', ' ')  -- 2 spaces (for odd leftovers)

RETURN @StrVal

END


1

Método 1

El primer método es reemplazar espacios adicionales entre palabras con una combinación de símbolos poco común como marcador temporal. Luego, puede reemplazar los símbolos de marcadores temporales utilizando la función de reemplazo en lugar de un bucle.

Aquí hay un ejemplo de código que reemplaza el texto dentro de una variable de cadena.

DECLARE @testString AS VARCHAR(256) = ' Test        text   with  random*        spacing. Please normalize  this spacing!';
SELECT REPLACE(REPLACE(REPLACE(@testString, ' ', '*^'), '^*', ''), '*^', ' ');

Prueba de tiempo de ejecución n. ° 1: en diez ejecuciones de este método de reemplazo, el tiempo de espera promedio en las respuestas del servidor fue de 1.7 milisegundos y el tiempo total de ejecución fue de 4.6 milisegundos. Prueba de tiempo de ejecución n. ° 2: el tiempo medio de espera en las respuestas del servidor fue de 1,7 milisegundos y el tiempo total de ejecución fue de 3,7 milisegundos.

Método # 2

El segundo método no es tan elegante como el primero, pero también hace el trabajo. Este método funciona anidando cuatro (u opcionalmente más) declaraciones de reemplazo que reemplazan dos espacios en blanco con un espacio en blanco.

DECLARE @testString AS VARCHAR(256) = ' Test        text   with  random*        spacing. Please normalize  this spacing!';
SELECT REPLACE(REPLACE(REPLACE(REPLACE(@testString,' ',' '),' ',' '),' ',' '),' ',' ')

Prueba de tiempo de ejecución n. ° 1: en diez ejecuciones de este método de reemplazo, el tiempo de espera promedio en las respuestas del servidor fue de 1.9 milisegundos y el tiempo de ejecución total fue de 3.8 milisegundos. Prueba de tiempo de ejecución n. ° 2: el tiempo medio de espera en las respuestas del servidor fue de 1,8 milisegundos y el tiempo total de ejecución fue de 4,8 milisegundos.

Método # 3

El tercer método para reemplazar espacios adicionales entre palabras es usar un bucle simple. Puede verificar los espacios adicionales en un ciclo while y luego usar la función de reemplazo para reducir los espacios adicionales con cada iteración del ciclo.

DECLARE @testString AS VARCHAR(256) = ' Test text with random* spacing. Please normalize this spacing!';
WHILE CHARINDEX(' ',@testString) > 0
SET @testString = REPLACE(@testString, ' ', ' ')
SELECT @testString

Prueba de tiempo de ejecución n. ° 1: en diez ejecuciones de este método de reemplazo, el tiempo de espera promedio en las respuestas del servidor fue de 1.8 milisegundos y el tiempo total de ejecución fue de 3.4 milisegundos. Prueba de tiempo de ejecución n. ° 2: el tiempo medio de espera en las respuestas del servidor fue de 1,9 milisegundos y el tiempo total de ejecución fue de 2,8 milisegundos.


1

Esta es la solución a través de reemplazo múltiple, que funciona para cualquier cadena (no necesita caracteres especiales, que no forman parte de la cadena).

declare @value varchar(max)
declare @result varchar(max)
set @value = 'alpha   beta gamma  delta       xyz'

set @result = replace(replace(replace(replace(replace(replace(replace(
  @value,'a','ac'),'x','ab'),'  ',' x'),'x ',''),'x',''),'ab','x'),'ac','a')

select @result -- 'alpha beta gamma delta xyz'

bueno, pero cambiando 'abe' por 'ax'
Adam Silenko

0

Utilizo la solución FOR XML PATH para reemplazar múltiples espacios en un solo espacio

La idea es reemplazar espacios con etiquetas XML Luego dividir la cadena XML en fragmentos de cadena sin etiquetas XML Finalmente, concatenar esos valores de cadena agregando caracteres de un solo espacio entre dos

Así es como se puede llamar a la función UDF final

select dbo.ReplaceMultipleSpaces('   Sample   text  with  multiple  space     ')

0
 DECLARE @str varchar(150)
SET @str='Hello    My   name  is Jiyaul   mustafa'
Select REPLACE(REPLACE(REPLACE(@str,' ','{}'),'}{',''),'{}',' ')

0

Normalmente uso este enfoque:

declare @s varchar(50)
set @s = 'TEST         TEST'
select REPLACE(REPLACE(REPLACE(@s,' ','[o][c]'),'[c][o]',''),'[o][c]',' ')

0

Solo agregando otro método

Reemplazo de múltiples espacios con un solo espacio SIN usar REPLACE en SQL Server-

DECLARE @TestTable AS TABLE(input VARCHAR(MAX));

INSERT INTO @TestTable VALUES
('HAPPY         NEWYEAR     2020'),
('WELCOME       ALL     !');

SELECT
    CAST('<r><![CDATA[' + input + ']]></r>' AS XML).value('(/r/text())[1] cast as xs:token?','VARCHAR(MAX)')
    AS Expected_Result
FROM @TestTable;

--OUTPUT
/*
Expected_Result
HAPPY NEWYEAR 2020
WELCOME ALL !
*/

0

Por favor, busque el siguiente código

select trim(string_agg(value,' ')) from STRING_SPLIT('  single    spaces   only  ',' ')
where value<>' '

Esto funcionó para mí .. Espero que esto ayude ...


-1

Puedes probar esto:

select Regexp_Replace('single    spaces   only','( ){2,}', ' ') from dual;

DECLARE @str varchar (150) SET @ str = 'Hola, Bienvenido al mundo de .net' Seleccione REPLACE (REPLACE (REPLACE (@str, '', '{}'), '} {', ''), '{ } ',' ')
JIYAUL MUSTAPHA

-3
update mytable
set myfield = replace(myfield, '  ',  ' ')
where myfield like '%  %'

Prueba esto..


Llamé a esta solución en mis preguntas porque no satisface la necesidad, pero gracias.
Christoph
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.