แทนที่ช่องว่างที่ซ้ำกันด้วยช่องว่างเดียวใน T-SQL


103

ฉันต้องการให้แน่ใจว่าฟิลด์ที่กำหนดไม่มีช่องว่างมากกว่าหนึ่งช่อง (ฉันไม่ได้กังวลเกี่ยวกับพื้นที่สีขาวทั้งหมดเพียงแค่ช่องว่าง) ระหว่างอักขระ

ดังนั้น

'single    spaces   only'

จะต้องกลายเป็น

'single spaces only'

ด้านล่างจะไม่ทำงาน

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

มันจะส่งผลให้

'single  spaces  only'

ฉันชอบที่จะยึดติดกับ T-SQL ดั้งเดิมมากกว่าโซลูชันที่ใช้ CLR

ความคิด?


คุณสามารถทำได้ด้วยการแทนที่ REGEX
Raj More

คำตอบ:


333

เป็นระเบียบเรียบร้อยยิ่งขึ้น:

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

เอาท์พุต:

เลือกช่องว่างเดียว


6
หากคุณต้องการลบช่องว่างที่ด้านหน้าและด้านท้ายของสตริงให้ห่อการแทนที่ด้วย LTRIM, RTRIM และจะดำเนินการให้คุณ
Neil Knight

7
ตราบใดที่สตริงของคุณไม่มีเครื่องหมาย <หรือ> จำนวนมาก ดูเหมือนจะเปราะบางสำหรับความชอบของฉัน
JohnFx

9
แฮ็คที่สง่างามอย่างแท้จริง โหวตแล้ว สามารถใช้อักขระสองตัวใดก็ได้สำหรับส่วนตรงกลางถ้า <> อาจอยู่ในข้อความอินพุต
richardtallent

33
Chris คุณสามารถใช้อักขระ ASCII ที่ไม่สามารถพิมพ์ได้เช่น CHAR (17) และ CHAR (18) เนื่องจากสิ่งเหล่านี้จะไม่อยู่ในข้อความที่คุณป้อน ยังเร็วกว่าการวนซ้ำของคำตอบที่ยอมรับ
richardtallent

7
ฉันต้องดูสิ่งนี้สักครู่เพื่อดูว่าคุณใช้ "> <", '' ไม่มีช่องว่างแทนที่ แต่ตอนนี้ฉันเข้าใจแล้ว ... มันยอดเยี่ยมมาก ฉันชอบคำแนะนำของ @richardtallent มากในการใช้อักขระ ASCII ที่ไม่สามารถพิมพ์ได้ซึ่งชุดค่าผสมที่เพิ่มเข้ามาซึ่งสร้าง: REPLACE (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
การห่อฟังก์ชันและเปลี่ยน varchar (100) เป็น nvarchar (สูงสุด)
Christoph

ความแตกต่างระหว่างสคริปต์ของ James และ Neil คือ James ทำงานในขณะที่วนซ้ำซึ่งในประสบการณ์ส่วนตัวการที่มันทำงานแม้ว่า 50,000 ระเบียนของตารางมีแนวโน้มที่จะช้ามากดังนั้นคุณต้องสร้างเป็นขั้นตอนและส่งผ่านในบันทึกและบางส่วน งานที่คุณอาจไม่ได้รับอนุญาตให้สร้างขั้นตอนใหม่ของวงดนตรี การใช้งานของนีลต่อที่มีอยู่ฟังก์ชั่นเพราะใช้ <> ถ้าคุณมีสตริงเช่น"release < now"นั้นคุณจะได้รับ"release<><><<><>now", "release<<>now", "release< now"มันเหมือนกันกับคู่ของสัญลักษณ์ใด ๆ หากคุณมีหนึ่งเดียวของทั้งคู่แล้วก็จะย้าย
Memor-X

1
การเรียกใช้สิ่งนี้ผ่านระเบียน 50k ควรลดน้ำหนักอย่างรวดเร็วฉันจะตรวจสอบปัญหาอื่น ๆ หากเป็นปัญหาของคุณ
user3486773

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 () หลายครั้งเป็นการแฮ็ก แต่หากจำนวนช่องว่าง "พิเศษ" ที่คาดการณ์ไว้สามารถคาดเดาได้และค่อนข้างเล็กก็จะทำได้ดีและเป็นไปตามข้อกำหนดของ OP ที่จะไม่เรียกรหัส RegEx ผ่าน CLR
richardtallent

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

การแทนที่จะทำงานในช่องว่างสองช่องทั้งหมดโดยไม่จำเป็นต้องใส่การแทนที่หลายรายการ นี่คือโซลูชันตามชุด


นี่จะไม่ยุบ 4 ช่องว่างเป็น 2 หรือ?
Christoph

ฉันเรียกวิธีแก้ปัญหานี้ในคำถามของฉันว่าไม่ตรงตามความต้องการ แต่ขอบคุณ
Christoph

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
ฉันชอบแนวคิดของฟังก์ชันวนซ้ำสำหรับสิ่งนี้ มีสิ่งที่ต้องระวังหรือไม่?
Zach Smith

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

3

นี่คือฟังก์ชันง่ายๆที่ฉันสร้างขึ้นเพื่อทำความสะอาดช่องว่างก่อนหรือหลังและช่องว่างหลายช่องภายในสตริง มันจัดการได้อย่างสง่างามถึง 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'

สิ่งที่ดี แต่เปลี่ยน 'abe' เป็น 'ax'
Adam Silenko

0

ฉันใช้โซลูชัน FOR XML PATH เพื่อแทนที่ช่องว่างหลายช่องเป็นช่องว่างเดียว

แนวคิดคือการแทนที่ช่องว่างด้วยแท็ก XML จากนั้นแยกสตริง XML เป็นส่วนสตริงโดยไม่มีแท็ก XML ในที่สุดก็เชื่อมต่อค่าสตริงเหล่านั้นด้วยการเพิ่มอักขระช่องว่างเดียวระหว่างสอง

นี่คือวิธีการเรียกใช้ฟังก์ชัน UDF ขั้นสุดท้าย

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



0

เพียงแค่เพิ่มวิธีอื่น -

การแทนที่หลายช่องว่างด้วยช่องว่างเดียวโดยไม่ต้องใช้ REPLACE ใน 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 = 'สวัสดียินดีต้อนรับสู่ World of. net' เลือก REPLACE (REPLACE (REPLACE (@str, '', '{}'), '} {', ''), '{ } ',' ')
รหัส

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

ลองดูสิ ..


ฉันเรียกวิธีแก้ปัญหานี้ในคำถามของฉันว่าไม่ตรงตามความต้องการ แต่ขอบคุณ
Christoph
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.