Замініть дублікати пробілів одним пробілом у T-SQL


100

Мені потрібно переконатися, що в даному полі немає одного простору (я не переймаюся всім пробілом, просто простором) між символами.

Так

'single    spaces   only'

потрібно перетворити на

'single spaces only'

Нижче не вийде

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

як це призведе до

'single  spaces  only'

Я дійсно вважаю за краще дотримуватися рідного T-SQL, а не на основі CLR.

Думки?


Це можна зробити заміною REGEX
Raj More

Відповіді:


325

Ще охайніше:

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

Вихід:

виберіть окремі пробіли


6
Якщо ви хочете видалити пробіли на передній та кінці рядка, оберніть заміну в LTRIM, RTRIM, і це зробить це за вас.
Ніл Найт

5
Поки ваша рядок не містить багато знаків <або>. Здається, що мені подобається.
JohnFx

8
Воістину елегантний хак. Отримано. Будь-які два символи можуть бути використані для середньої частини, якщо <> потенційно є вхідним текстом.
richardtallent

32
Кріс, ви можете використовувати недрукувальні символи ASCII, такі як CHAR (17) та CHAR (18), оскільки вони НІКОЛИ не будуть у введеному тексті. Ще швидше, ніж циклічне прийняття відповіді.
richardtallent

7
Мені довелося на мить поглянути на це на хвилину, щоб зрозуміти, що ти використовуєш '> <', '' Ні місця не заміняєш, але тепер, коли я це отримую ... це дуже геніально. Мені дуже подобалося @richardtallent пропозиція використовувати символи ASCII, що не друкуються, комбінація яких додає: REPLACE (REPLACE (ЗАМІНА (LastName, '', 'CHAR (17) CHAR (18)' '),' CHAR (18 ) CHAR (17) ',' '),' CHAR (17) CHAR (18) ',' ')
Anthony Griggs

25

Це спрацювало б:

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

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

select @test

1
Загортання функції та зміна вархара (100) на nvarchar (макс.)
Крістоф

Різниця між сценаріями Джеймса та Ніла полягає в тому, що Джеймс працює, хоча в той час як цикл, який, за особистим досвідом, його запуску, хоча 50 000 записів таблиці, як правило, дуже повільний, тому вам потрібно створити його як процедуру і пройти в запис і деякі вакансії, можливо, у вас немає дозволу на створення нової процедури в діапазоні. Використовує Нейл на існуючі функції , оскільки він використовує <>, якщо у вас є рядок , як "release < now"тоді ви отримаєте "release<><><<><>now", "release<<>now", "release< now", його те ж саме з будь-якою парою символів, якщо у вас є один один з пари , то вона буде рухатися
Memor-X

1
Запуск цих записів через 50k повинен бути легшим, і я б розглядав інші проблеми, якщо це ваша проблема.
користувач3486773

17

Якщо ви знаєте, що не буде більше певної кількості пробілів підряд, ви можете просто вкласти заміну:

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

4 заміни повинні фіксувати до 16 послідовних пробілів (16, потім 8, потім 4, потім 2, потім 1)

Якщо це може бути значно довше, то вам доведеться виконати щось на зразок вбудованої функції:

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

    RETURN @str
END

Тоді просто робіть

SELECT dbo.strip_spaces(myText) FROM myTable

Бред, у мене був майже ідентичний код, але ти побив мене до Пошти, тому підняв заяву. Кілька викликів REPLACE () є хакерськими, але якщо кількість очікуваних "зайвих" просторів передбачувана і відносно невелика, це буде просто чудово і відповідатиме вимозі ОП не викликати код RegEx через CLR.
richardtallent

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

Заміна буде працювати на всіх подвійних просторах, не потрібно ставити кілька замін. Це рішення, засноване на наборі.


Хіба це не розвалить 4 пробіли на 2?
Крістоф

Я вирішив це рішення у своїх питаннях як не задоволення потреби, а спасибі.
Крістоф

6

Це можна зробити рекурсивно за допомогою функції:

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

то, наприклад:

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

повертає:

NewStr
some string with many spaces

Або рішення, засноване на методі, описаному @ agdk26 або @Neil Knight (але безпечніше),
обидва приклади повертають вихідний результат вище:

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

або

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

Як це працює: введіть тут опис зображення

Застереження:
Char / string, які використовуються для заміни пробілів, не повинні існувати на початку або в кінці рядка і стояти окремо.


1
Мені подобається ідея рекурсивної функції для цього. чи варто щось знати?
Зак Сміт

5

Це дещо жорстока сила, але спрацює

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

Ось проста функція, яку я створив для очищення будь-яких просторів до або після, та декількох пробілів у рядку. Він витончено обробляє приблизно 108 пробілів за один розтяг та стільки ж блоків, скільки є в рядку. Ви можете збільшити це за допомогою коефіцієнтів 8, додавши додаткові рядки з більшими шматками пробілів, якщо вам потрібно. Це, здається, працює швидко і не викликає проблем, незважаючи на загальне використання у великому застосуванні.

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

Знайшов це під час копання відповіді:

SELECT REPLACE(
        REPLACE(
             REPLACE(
                LTRIM(RTRIM('1 2  3   4    5     6'))
            ,'  ',' '+CHAR(7))
        ,CHAR(7)+' ','')
    ,CHAR(7),'') AS CleanString
where charindex('  ', '1 2  3   4    5     6') > 0

Повна відповідь (із поясненням) була взята з: http://techtipsbysatish.blogspot.com/2010/08/sql-server-replace-multiple-spaces-with.html

З другого погляду, здається, це лише дещо інша версія обраної відповіді.


1

Спосіб №1

Перший спосіб полягає в заміні зайвих пробілів між словами на незвичайне поєднання символів у якості тимчасового маркера. Потім ви можете замінити символи тимчасового маркера за допомогою функції заміни, а не циклу.

Ось приклад коду, який замінює текст у змінній String.

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

Тест часу виконання №1: За десять запусків цього методу заміни середній час очікування відповідей сервера становив 1,7 мілісекунди, а загальний час виконання - 4,6 мілісекунд. Тест часу виконання №2: Середній час очікування відповідей сервера становив 1,7 мілісекунди, а загальний час виконання - 3,7 мілісекунд.

Спосіб №2

Другий метод не такий елегантний, як перший, але також виконує роботу. Цей метод працює шляхом введення чотирьох (або необов'язково більше) заміни операторів, які замінюють два порожні пробіли одним порожнім пробілом.

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

Тест часу виконання №1: За десять запусків цього способу заміни середній час очікування відповідей сервера становив 1,9 мілісекунд, а загальний час виконання - 3,8 мілісекунд. Тест часу виконання №2: Середній час очікування відповідей сервера становив 1,8 мілісекунди, а загальний час виконання - 4,8 мілісекунди.

Метод №3

Третій спосіб заміни зайвих пробілів між словами - це використання простого циклу. Ви можете зробити перевірку додаткових пробілів у циклі, а потім використовувати функцію заміни, щоб зменшити зайві пробіли з кожною ітерацією циклу.

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

Тест часу виконання №1: За десять запусків цього способу заміни середній час очікування відповідей сервера становив 1,8 мілісекунди, а загальний час виконання - 3,4 мілісекунди. Тест часу виконання №2: Середній час очікування відповідей сервера становив 1,9 мілісекунд, а загальний час виконання - 2,8 мілісекунд.


1

Це рішення через багаторазову заміну, яка працює для будь-яких рядків (не потрібні спеціальні символи, які не входять до рядка).

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'

приємна річ, але змінити "абе" на "сокиру"
Адам Силенко,

0

Я використовую рішення для XML PATH для заміни декількох пробілів в єдиний простір

Ідея полягає в тому, щоб замінити пробіли тегами XML. Потім розділити рядок XML на фрагменти рядків без тегів XML Нарешті об'єднати ці рядкові значення, додавши один пробіл між двома символами

Ось як можна назвати остаточну функцію UDF

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

Я зазвичай використовую такий підхід:

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

0

Просто додавання іншого методу -

Заміна декількох просторів на один простір БЕЗ використання ЗАМИКИ в 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

Знайдіть нижче код

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

Це працювало для мене .. Сподіваюся, це допомагає ...


-1

Ви можете спробувати це:

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

DECLARE @str varchar (150) SET @ str = 'Привіт, Ласкаво просимо у світ .net' Виберіть ЗАМЕНИТИ (ЗАМІНА (ЗАМІНА (@str, '', '{}'), '} {', '),' { } ',' ')
Код

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

Спробуйте це..


Я вирішив це рішення у своїх питаннях як не задоволення потреби, а спасибі.
Крістоф
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.