Thay thế các khoảng trắng trùng lặp bằng một khoảng trắng trong T-SQL


100

Tôi cần đảm bảo rằng một trường nhất định không có nhiều hơn một khoảng trắng (tôi không quan tâm đến tất cả khoảng trắng, chỉ là khoảng trắng) giữa các ký tự.

Vì thế

'single    spaces   only'

cần được biến thành

'single spaces only'

Bên dưới sẽ không hoạt động

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

vì nó sẽ dẫn đến

'single  spaces  only'

Tôi thực sự muốn gắn bó với T-SQL gốc hơn là một giải pháp dựa trên CLR.

Suy nghĩ?


Bạn có thể làm điều này với một thay thế REGEX
Raj More

Câu trả lời:


325

Ngay cả ngăn nắp:

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

Đầu ra:

chọn không gian đơn


6
Nếu bạn muốn loại bỏ khoảng trắng ở đầu và cuối chuỗi, hãy bọc phần thay thế trong LTRIM, RTRIM và nó sẽ làm điều đó cho bạn.
Neil Knight

5
Miễn là chuỗi của bạn không chứa nhiều dấu <hoặc>. Có vẻ mong manh đối với ý thích của tôi.
JohnFx

8
Hack thực sự tao nhã. Đã ủng hộ. Hai ký tự bất kỳ có thể được sử dụng cho phần giữa nếu <> có thể có trong văn bản đầu vào.
richardtallent

32
Chris, bạn có thể sử dụng các ký tự ASCII không in được như CHAR (17) và CHAR (18), vì chúng KHÔNG BAO GIỜ có trong văn bản đầu vào của bạn. Vẫn nhanh hơn vòng lặp của câu trả lời được chấp nhận.
richardtallent

7
Tôi đã phải thực sự nhìn vào điều này một lúc để tìm ra bạn bạn đã sử dụng '> <', '' Không có thay thế dấu cách nhưng bây giờ tôi đã hiểu nó ... nó rất tuyệt vời. Tôi đã làm rất giống đề xuất của @richardtallent về việc sử dụng các ký tự ASCII không in được, tổ hợp được thêm vào của chúng tạo ra: REPLACE (REPLACE (REPLACE (LastName, '', 'CHAR (17) CHAR (18)'), 'CHAR (18 ) CHAR (17) ',' '),' CHAR (17) CHAR (18) ',' ')
Anthony Griggs

25

Điều này sẽ hoạt động:

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

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

select @test

1
Gói chức năng và thay đổi varchar (100) thành nvarchar (tối đa)
Christoph

Sự khác biệt giữa các tập lệnh của James và Neil là James chạy mặc dù trong khi vòng lặp, theo kinh nghiệm cá nhân, để nó chạy qua 50.000 bản ghi của một bảng có xu hướng rất chậm, vì vậy bạn cần tạo nó như một thủ tục và chuyển vào một bản ghi và một số công việc mà bạn có thể không có quyền tạo một thủ tục mới của ban nhạc. Sử dụng Neil của mỗi hiện chức năng vì nó sử dụng <>, nếu bạn có một chuỗi như "release < now"sau đó bạn sẽ nhận được "release<><><<><>now", "release<<>now", "release< now", nó tương tự với bất kỳ cặp biểu tượng, nếu bạn có một duy nhất của cặp sau đó nó sẽ di chuyển
Memor-X

1
chạy qua 50k bản ghi này sẽ nhanh chóng nhẹ nhàng, tôi sẽ xem xét các vấn đề khác nếu đó là vấn đề của bạn.
user3486773

17

Nếu bạn biết sẽ không có nhiều hơn một số khoảng trắng nhất định trong một hàng, bạn có thể chỉ cần lồng thay thế:

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

4 thay thế sẽ sửa chữa tối đa 16 khoảng trắng liên tiếp (16, sau đó 8, sau đó 4, sau đó 2, sau đó 1)

Nếu nó có thể dài hơn đáng kể, thì bạn phải thực hiện một cái gì đó giống như một hàm trong dòng:

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

    RETURN @str
END

Sau đó, chỉ cần làm

SELECT dbo.strip_spaces(myText) FROM myTable

Brad, tôi có mã gần như giống hệt nhau nhưng bạn đã đánh bại tôi về bài đăng, vì vậy hãy ủng hộ. Nhiều lệnh gọi REPLACE () là khó đoán, nhưng nếu số lượng khoảng trắng "thừa" dự kiến ​​có thể dự đoán được và tương đối nhỏ, nó sẽ hoạt động tốt và đáp ứng yêu cầu của OP là không gọi mã RegEx qua CLR.
richardtallent

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

Thay thế sẽ hoạt động trên tất cả các khoảng trắng, không cần đặt nhiều thay thế. Đây là giải pháp dựa trên thiết lập.


Điều này sẽ không thu gọn 4 không gian thành 2?
Christoph

Tôi đã gọi giải pháp này trong các câu hỏi của mình là không đáp ứng được nhu cầu, nhưng cảm ơn.
Christoph

6

Nó có thể được thực hiện đệ quy thông qua hàm:

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

sau đó, ví dụ:

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

trả lại:

NewStr
some string with many spaces

Hoặc giải pháp dựa trên phương pháp được mô tả bởi @ agdk26 hoặc @Neil Knight (nhưng an toàn hơn)
cả hai ví dụ đều trả về kết quả ở trên:

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

hoặc là

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

Làm thế nào nó hoạt động: nhập mô tả hình ảnh ở đây

Thận trọng: Biểu đồ
/ chuỗi được sử dụng để thay thế khoảng trắng không được tồn tại ở đầu hoặc cuối chuỗi và đứng một mình.


1
Tôi giống như ý tưởng về một hàm đệ quy cho điều này. có điều gì cần lưu ý không?
Zach Smith,

5

Điều này hơi vũ phu, nhưng sẽ hiệu quả

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

Đây là một hàm đơn giản mà tôi đã tạo để làm sạch bất kỳ khoảng trắng nào trước hoặc sau và nhiều khoảng trắng trong một chuỗi. Nó xử lý một cách duyên dáng lên đến khoảng 108 khoảng trống trong một lần kéo dài và nhiều khối như có trong chuỗi. Bạn có thể tăng điều đó lên hệ số 8 bằng cách thêm các dòng bổ sung với các phần không gian lớn hơn nếu bạn cần. Nó dường như hoạt động nhanh chóng và không gây ra bất kỳ vấn đề nào mặc dù nó được sử dụng phổ biến trong một ứng dụng lớ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

Tìm thấy điều này khi đang tìm kiếm câu trả lời:

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

Câu trả lời đầy đủ (có giải thích) được lấy từ: http://techtipsbysatish.blogspot.com/2010/08/sql-server-replace-multiple-spaces-with.html

Ở cái nhìn thứ hai, dường như chỉ là một phiên bản hơi khác của câu trả lời đã chọn.


1

Phương pháp # 1

Phương pháp đầu tiên là thay thế các khoảng trắng thừa giữa các từ bằng một tổ hợp ký hiệu không phổ biến làm điểm đánh dấu tạm thời. Sau đó, bạn có thể thay thế các ký hiệu đánh dấu tạm thời bằng cách sử dụng chức năng thay thế thay vì một vòng lặp.

Đây là một ví dụ mã thay thế văn bản trong một biến Chuỗi.

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

Kiểm tra thời gian thực thi # 1: Trong mười lần chạy phương pháp thay thế này, thời gian chờ trung bình trên các phản hồi của máy chủ là 1,7 mili giây và tổng thời gian thực thi là 4,6 mili giây. Kiểm tra thời gian thực thi # 2: Thời gian chờ trung bình trên các câu trả lời của máy chủ là 1,7 mili giây và tổng thời gian thực thi là 3,7 mili giây.

Phương pháp # 2

Phương pháp thứ hai không hoàn toàn thanh lịch như phương pháp đầu tiên, nhưng cũng hoàn thành công việc. Phương pháp này hoạt động bằng cách lồng bốn câu lệnh thay thế (hoặc tùy chọn nhiều hơn) thay thế hai dấu cách trống bằng một dấu cách trống.

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

Kiểm tra thời gian thực thi # 1: Trong mười lần chạy phương pháp thay thế này, thời gian chờ trung bình trên các phản hồi của máy chủ là 1,9 mili giây và tổng thời gian thực thi là 3,8 mili giây. Kiểm tra thời gian thực thi # 2: Thời gian chờ trung bình trên các câu trả lời của máy chủ là 1,8 mili giây và tổng thời gian thực thi là 4,8 mili giây.

Phương pháp # 3

Phương pháp thứ ba để thay thế khoảng trắng thừa giữa các từ là sử dụng một vòng lặp đơn giản. Bạn có thể kiểm tra các khoảng trắng thừa trong vòng lặp while và sau đó sử dụng hàm thay thế để giảm các khoảng trắng thừa với mỗi lần lặp lại của vòng lặp.

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

Kiểm tra thời gian thực thi # 1: Trong mười lần chạy phương pháp thay thế này, thời gian chờ trung bình trên các phản hồi của máy chủ là 1,8 mili giây và tổng thời gian thực thi là 3,4 mili giây. Kiểm tra thời gian thực thi # 2: Thời gian chờ trung bình trên các câu trả lời của máy chủ là 1,9 mili giây và tổng thời gian thực thi là 2,8 mili giây.


1

Đây là giải pháp thông qua thay thế nhiều lần, hoạt động cho bất kỳ chuỗi nào (không cần ký tự đặc biệt, không phải là một phần của chuỗi).

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'

điều tốt, nhưng thay đổi 'abe' thành 'ax'
Adam Silenko

0

Tôi sử dụng giải pháp FOR XML PATH để thay thế nhiều khoảng trắng thành một khoảng trắng

Ý tưởng là thay thế khoảng trắng bằng các thẻ XML Sau đó chia chuỗi XML thành các đoạn chuỗi không có thẻ XML Cuối cùng nối các giá trị chuỗi đó bằng cách thêm các ký tự khoảng trắng đơn vào giữa hai

Đây là cách hàm UDF cuối cùng có thể được gọi

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

Tôi thường sử dụng phương pháp này:

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

0

Chỉ cần thêm một phương pháp khác-

Thay thế nhiều không gian bằng một không gian mà không sử dụng thay thế trong 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

Vui lòng Tìm mã bên dưới

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

Điều này đã làm việc cho tôi .. Hy vọng điều này sẽ giúp ...


-1

Bạn có thể thử điều này:

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

DECLARE @str varchar (150) SET @ str = 'Hello Welcome to World of .net' Chọn REPLACE (THAY THẾ (REPLACE (@str, '', '{}'), '} {', ''), '{ } ',' ')
JIYAUL MUSTAPHA

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

Thử cái này..


Tôi đã gọi giải pháp này trong các câu hỏi của mình là không đáp ứng được nhu cầu, nhưng cảm ơn.
Christoph
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.