Remplacez les espaces en double par un seul espace dans T-SQL


100

Je dois m'assurer qu'un champ donné n'a pas plus d'un espace (je ne suis pas préoccupé par tous les espaces blancs, juste l'espace) entre les caractères.

Alors

'single    spaces   only'

doit être transformé en

'single spaces only'

Le ci-dessous ne fonctionnera pas

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

car cela entraînerait

'single  spaces  only'

Je préférerais vraiment m'en tenir à T-SQL natif plutôt qu'à une solution basée sur CLR.

Pensées?


Vous pouvez le faire avec un remplacement REGEX
Raj More

Réponses:


326

Encore plus ordonné:

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

Production:

sélectionner des espaces simples


6
Si vous souhaitez supprimer les espaces à l'avant et à la fin de la chaîne, enveloppez le remplacement dans un LTRIM, RTRIM et il le fera pour vous.
Neil Knight

5
Tant que votre chaîne ne contient pas beaucoup de signes <ou>. Semble fragile à mon goût.
JohnFx

8
Hack vraiment élégant. J'ai voté pour. Deux caractères quelconques peuvent être utilisés pour la partie centrale si <> se trouve potentiellement dans le texte d'entrée.
richardtallent

32
Chris, vous pouvez utiliser des caractères ASCII non imprimables comme CHAR (17) et CHAR (18), car ils ne seront JAMAIS dans votre texte d'entrée. Toujours plus rapide que le bouclage de la réponse acceptée.
richardtallent

7
J'ai dû vraiment regarder ça pendant un moment pour comprendre que vous aviez utilisé le '> <', '' Aucun espace à remplacer, mais maintenant que je comprends ... c'est très brillant. J'ai beaucoup aimé la suggestion de @richardtallent d'utiliser les caractères ASCII non imprimables dont la combinaison ajoutée produit: REPLACE (REPLACE (REPLACE (LastName, '', 'CHAR (17) CHAR (18)'), 'CHAR (18 ) CHAR (17) ',' '),' CHAR (17) CHAR (18) ',' ')
Anthony Griggs

25

Cela fonctionnerait:

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

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

select @test

1
Emballage de la fonction et changement de varchar (100) en nvarchar (max)
Christoph

La différence entre les scripts de James et de Neil est que James exécute une boucle while qui, selon l'expérience personnelle, le faire exécuter à travers 50000 enregistrements d'une table a tendance à être très lent, vous devez donc le créer en tant que procédure et passer un enregistrement et certains jobs, vous n'avez peut-être pas l'autorisation de créer une nouvelle procédure de bande. Les utilisations de Neil fonctions par existant car il utilise <>, si vous avez une chaîne comme "release < now"vous obtiendrez "release<><><<><>now", "release<<>now", "release< now", son même avec une paire de symboles, si vous avez un seul de la paire alors il va se déplacer
Memor-X

1
exécuter cela à travers 50k enregistrements devrait être rapide, je me pencherais sur d'autres problèmes si c'est votre problème.
user3486773

17

Si vous savez qu'il n'y aura pas plus d'un certain nombre d'espaces dans une ligne, vous pouvez simplement imbriquer le remplacement:

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

4 remplacements devraient corriger jusqu'à 16 espaces consécutifs (16, puis 8, puis 4, puis 2, puis 1)

Si cela pouvait être beaucoup plus long, alors vous devriez faire quelque chose comme une fonction en ligne:

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

    RETURN @str
END

Alors fais juste

SELECT dbo.strip_spaces(myText) FROM myTable

Brad, j'avais un code presque identique, mais vous m'avez battu au Post, alors votez pour. Les appels multiples à REPLACE () sont hackish, mais si le nombre d'espaces "supplémentaires" attendus est prévisible et relativement petit, cela fera très bien et répondra à l'exigence de l'OP de ne pas appeler le code RegEx via le CLR.
richardtallent

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

Remplacer fonctionnera sur tous les espaces doubles, pas besoin de mettre plusieurs remplacements. C'est la solution basée sur les ensembles.


Cela ne réduirait-il pas 4 espaces en 2?
Christoph

J'ai appelé cette solution dans mes questions comme ne répondant pas au besoin, mais merci.
Christoph

6

Cela peut être fait récursivement via la fonction:

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

puis, par exemple:

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

Retour:

NewStr
some string with many spaces

Ou la solution basée sur la méthode décrite par @ agdk26 ou @Neil Knight (mais plus sûre), les
deux exemples renvoient la sortie ci-dessus:

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...

ou

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

Comment ça fonctionne: entrez la description de l'image ici

Attention: le
caractère / chaîne utilisé pour remplacer les espaces ne doit pas exister au début ou à la fin de la chaîne et doit être autonome.


1
J'aime un peu l'idée d'une fonction récursive pour cela. y a-t-il quelque chose à savoir?
Zach Smith

5

C'est un peu de la force brute, mais cela fonctionnera

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

Voici une fonction simple que j'ai créée pour nettoyer tous les espaces avant ou après, et plusieurs espaces dans une chaîne. Il gère gracieusement jusqu'à environ 108 espaces en un seul tronçon et autant de blocs qu'il y a dans la chaîne. Vous pouvez augmenter cela par des facteurs de 8 en ajoutant des lignes supplémentaires avec de plus grands morceaux d'espaces si vous en avez besoin. Il semble fonctionner rapidement et n'a causé aucun problème malgré son utilisation généralisée dans une grande application.

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éthode n ° 1

La première méthode consiste à remplacer les espaces supplémentaires entre les mots par une combinaison de symboles inhabituelle comme marqueur temporaire. Ensuite, vous pouvez remplacer les symboles de marqueurs temporaires en utilisant la fonction de remplacement plutôt qu'une boucle.

Voici un exemple de code qui remplace le texte dans une variable String.

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

Test de temps d'exécution n ° 1: en dix exécutions de cette méthode de remplacement, le temps d'attente moyen des réponses du serveur était de 1,7 millisecondes et le temps d'exécution total était de 4,6 millisecondes. Test de temps d'exécution n ° 2: le temps d'attente moyen des réponses du serveur était de 1,7 millisecondes et le temps d'exécution total était de 3,7 millisecondes.

Méthode n ° 2

La deuxième méthode n'est pas aussi élégante que la première, mais elle fait également le travail. Cette méthode fonctionne en imbriquant quatre instructions de remplacement (ou éventuellement plus) qui remplacent deux espaces vides par un espace vide.

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

Test de temps d'exécution n ° 1: en dix exécutions de cette méthode de remplacement, le temps d'attente moyen des réponses du serveur était de 1,9 millisecondes et le temps d'exécution total était de 3,8 millisecondes. Test de temps d'exécution n ° 2: le temps d'attente moyen des réponses du serveur était de 1,8 millisecondes et le temps d'exécution total était de 4,8 millisecondes.

Méthode n ° 3

La troisième méthode pour remplacer les espaces supplémentaires entre les mots consiste à utiliser une simple boucle. Vous pouvez vérifier les espaces supplémentaires dans une boucle while, puis utiliser la fonction de remplacement pour réduire les espaces supplémentaires à chaque itération de la boucle.

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

Test du temps d'exécution n ° 1: en dix exécutions de cette méthode de remplacement, le temps d'attente moyen des réponses du serveur était de 1,8 millisecondes et le temps d'exécution total était de 3,4 millisecondes. Test de temps d'exécution n ° 2: le temps d'attente moyen des réponses du serveur était de 1,9 millisecondes et le temps d'exécution total était de 2,8 millisecondes.


1

C'est la solution via le remplacement multiple, qui fonctionne pour toutes les chaînes (n'a pas besoin de caractères spéciaux, qui ne font pas partie de la chaîne).

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'

bonne chose, mais changer 'abe' en 'ax'
Adam Silenko

0

J'utilise la solution FOR XML PATH pour remplacer plusieurs espaces en un seul espace

L'idée est de remplacer les espaces par des balises XML Puis diviser la chaîne XML en fragments de chaîne sans balises XML Enfin concaténer ces valeurs de chaîne en ajoutant des espaces simples entre deux

Voici comment la fonction UDF finale peut être appelée

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

J'utilise généralement cette approche:

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

0

Juste ajouter une autre méthode-

Remplacement de plusieurs espaces par un seul espace SANS utiliser REPLACE dans 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

Veuillez trouver ci-dessous le code

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

Cela a fonctionné pour moi .. J'espère que cela aide ...


-1

Vous pouvez essayer ceci:

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

DECLARE @str varchar (150) SET @ str = 'Hello Welcome to World of .net' Sélectionnez REPLACE (REPLACE (REPLACE (@str, '', '{}'), '} {', ''), '{ } ',' ')
Code

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

Essaye ça..


J'ai appelé cette solution dans mes questions comme ne répondant pas au besoin, mais merci.
Christoph
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.