Thay thế một dòng mới trong TSQL


414

Tôi muốn thay thế (hoặc xóa) một ký tự dòng mới trong chuỗi TSQL. Bất kỳ ý tưởng?

Rõ ràng

REPLACE(@string, CHAR(13), '')

sẽ không làm điều đó ...

Câu trả lời:


843

Trên thực tế, một dòng mới trong một lệnh SQL hoặc chuỗi script có thể là bất kỳ CR, LF hoặc CR + LF. Để có được tất cả, bạn cần một cái gì đó như thế này:

SELECT REPLACE(REPLACE(@str, CHAR(13), ''), CHAR(10), '')

5
@NielsBrinch Điều đó sẽ hoạt động tốt miễn là đó là loại ngắt dòng duy nhất trong chuỗi của bạn. Nhưng SQL Server không hỗ trợ cả ba loại. Trên thực tế, nếu bạn đã từng trích xuất tất cả các quy trình được lưu trữ trong hệ thống và các chế độ xem theo kịch bản, bạn có thể tìm thấy các phiên bản của cả ba do chính Microsoft sử dụng.
RBarryYoung

Điều này làm việc cho tôi b / c trước khi tôi thực hiện thay đổi này sao chép và dán dữ liệu cột sẽ có con trỏ ở cuối văn bản với hai khoảng trắng. Sau khi thực hiện thay đổi này, sao chép và dán vào notepad có con trỏ ngồi trực tiếp ở cuối văn bản. Nó đã gây ra sự cố cho tôi trong GUI phía trước của chúng tôi, dòng char mới đang hiển thị.
natur3

8
Nếu kiểu dữ liệu cột là văn bản thì trước tiên bạn cần truyền sang nvarchar sau đó thay thế CHỌN LẠI (REPLACE (cast (@str dưới dạng nvarchar (max)), CHAR (13), ''), CHAR (10), '')
akd

1
@Slint Vâng, điểm tốt. Thực tế, để sử dụng mã này từ mã máy khách, bạn nên thêm một tên cột. Mặc dù sự thật là rất nhiều lần bạn có thể thoát khỏi việc sử dụng .columns[0]thay thế.
RBarryYoung

2
Đối với phiên bản Oracle tôi đang sử dụng, câu lệnh là CHR, không phải CHAR. Chỉ trong trường hợp ai đó đang cố gắng gỡ lỗi từ Oracle. Nếu không, mọi thứ khác áp dụng.
Sedona

143
REPLACE(@string, CHAR(13) + CHAR(10), '')

2
Đây là phương pháp tôi đã thử đầu tiên, nhưng nó không hoạt động đáng tin cậy cho tất cả dữ liệu. @RBarryYoung có nó ở trên.
Mark W Dickson

1
cảm ơn, tôi đã phải sửa đổi điều này một chút để làm việc cho tôi, trong trường hợp của tôi là: thay thế (REPLACE (@ chuỗi, CHAR (13), ''), CHAR (10), '')
user734028

36

Tôi có thể trễ bữa tiệc một năm, nhưng tôi làm việc với các truy vấn & MS-SQL mỗi ngày và tôi cảm thấy mệt mỏi với các hàm tích hợp LTRIM () & RTRIM () (và luôn phải gọi chúng cùng nhau), và cuối cùng không bắt được dữ liệu 'bẩn' có dòng mới, vì vậy tôi quyết định đã đến lúc phải thực hiện chức năng TRIM tốt hơn. Tôi hoan nghênh phản hồi của bạn bè!

Tuyên bố miễn trừ trách nhiệm : điều này thực sự loại bỏ (thay thế bằng một khoảng trắng duy nhất) các dạng khoảng trắng mở rộng (tab, nguồn cấp dữ liệu, trả lại vận chuyển, v.v.), do đó, nó được đổi tên thành "CleanAndTrim" từ câu trả lời ban đầu của tôi. Ý tưởng ở đây là chuỗi của bạn không cần thêm các ký tự khoảng trắng đặc biệt như vậy bên trong nó, và vì vậy nếu chúng không xuất hiện ở đầu / đuôi, chúng nên được thay thế bằng một khoảng trắng. Nếu bạn cố tình lưu trữ các ký tự như vậy trong chuỗi của bạn (giả sử, cột dữ liệu mà bạn sắp chạy này), ĐỪNG LÀM NÓ! Cải thiện chức năng này hoặc viết riêng của bạn theo nghĩa đen chỉ cần loại bỏ các ký tự đó khỏi các điểm cuối của chuỗi, chứ không phải từ 'cơ thể'.

Được rồi, bây giờ từ chối trách nhiệm được cập nhật, đây là mã.

-- =============================================
-- Description: TRIMs a string 'for real' - removes standard whitespace from ends,
-- and replaces ASCII-char's 9-13, which are tab, line-feed, vert tab,
-- form-feed, & carriage-return (respectively), with a whitespace
-- (and then trims that off if it's still at the beginning or end, of course).
-- =============================================
CREATE FUNCTION [fn_CleanAndTrim] (
       @Str nvarchar(max)
)
RETURNS nvarchar(max) AS
BEGIN
       DECLARE @Result nvarchar(max)

       SET @Result = LTRIM(RTRIM(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
              LTRIM(RTRIM(@Str)), CHAR(9), ' '), CHAR(10), ' '), CHAR(11), ' '), CHAR(12), ' '), CHAR(13), ' ')))

       RETURN @Result
END

Chúc mừng!

Tuyên bố miễn trừ trách nhiệm khác : Ngắt dòng Windows điển hình của bạn là CR + LF, vì vậy nếu chuỗi của bạn chứa những thứ đó, cuối cùng bạn sẽ thay thế chúng bằng khoảng trắng "kép".

CẬP NHẬT, 2016 : Một phiên bản mới cung cấp cho bạn tùy chọn để thay thế các ký tự khoảng trắng đặc biệt đó bằng các ký tự khác bạn chọn! Điều này cũng bao gồm bình luận và giải quyết vấn đề ghép nối Windows CR + LF, tức là thay thế cặp char cụ thể đó bằng một thay thế duy nhất.

IF OBJECT_ID('dbo.fn_CleanAndTrim') IS NULL
    EXEC ('CREATE FUNCTION dbo.fn_CleanAndTrim () RETURNS INT AS BEGIN RETURN 0 END')
GO
-- =============================================
-- Author: Nate Johnson
-- Source: http://stackoverflow.com/posts/24068265
-- Description: TRIMs a string 'for real' - removes standard whitespace from ends,
-- and replaces ASCII-char's 9-13, which are tab, line-feed, vert tab, form-feed,
-- & carriage-return (respectively), with a whitespace or specified character(s).
-- Option "@PurgeReplaceCharsAtEnds" determines whether or not to remove extra head/tail
-- replacement-chars from the string after doing the initial replacements.
-- This is only truly useful if you're replacing the special-chars with something
-- **OTHER** than a space, because plain LTRIM/RTRIM will have already removed those.
-- =============================================
ALTER FUNCTION dbo.[fn_CleanAndTrim] (
    @Str NVARCHAR(MAX)
    , @ReplaceTabWith NVARCHAR(5) = ' '
    , @ReplaceNewlineWith NVARCHAR(5) = ' '
    , @PurgeReplaceCharsAtEnds BIT = 1
)
RETURNS NVARCHAR(MAX) AS
BEGIN
    DECLARE @Result NVARCHAR(MAX)

    --The main work (trim & initial replacements)
    SET @Result = LTRIM(RTRIM(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
        LTRIM(RTRIM(@Str))  --Basic trim
        , NCHAR(9), @ReplaceTabWith), NCHAR(11), @ReplaceTabWith)   --Replace tab & vertical-tab
        , (NCHAR(13) + NCHAR(10)), @ReplaceNewlineWith) --Replace "Windows" linebreak (CR+LF)
        , NCHAR(10), @ReplaceNewlineWith), NCHAR(12), @ReplaceNewlineWith), NCHAR(13), @ReplaceNewlineWith)))   --Replace other newlines

    --If asked to trim replacement-char's from the ends & they're not both whitespaces
    IF (@PurgeReplaceCharsAtEnds = 1 AND NOT (@ReplaceTabWith = N' ' AND @ReplaceNewlineWith = N' '))
    BEGIN
        --Purge from head of string (beginning)
        WHILE (LEFT(@Result, DATALENGTH(@ReplaceTabWith)/2) = @ReplaceTabWith)
            SET @Result = SUBSTRING(@Result, DATALENGTH(@ReplaceTabWith)/2 + 1, DATALENGTH(@Result)/2)

        WHILE (LEFT(@Result, DATALENGTH(@ReplaceNewlineWith)/2) = @ReplaceNewlineWith)
            SET @Result = SUBSTRING(@Result, DATALENGTH(@ReplaceNewlineWith)/2 + 1, DATALENGTH(@Result)/2)

        --Purge from tail of string (end)
        WHILE (RIGHT(@Result, DATALENGTH(@ReplaceTabWith)/2) = @ReplaceTabWith)
            SET @Result = SUBSTRING(@Result, 1, DATALENGTH(@Result)/2 - DATALENGTH(@ReplaceTabWith)/2)

        WHILE (RIGHT(@Result, DATALENGTH(@ReplaceNewlineWith)/2) = @ReplaceNewlineWith)
            SET @Result = SUBSTRING(@Result, 1, DATALENGTH(@Result)/2 - DATALENGTH(@ReplaceNewlineWith)/2)
    END

    RETURN @Result
END
GO

Người dùng trước đây, vui lòng lưu ý thay đổi và từ chối trách nhiệm - và tôi xin lỗi vì những giả định ban đầu về việc sử dụng & mục đích.
NateJ

1
Cập nhật mới! Các trường hợp thử nghiệm có thể được tìm thấy ở đây: sqlfiddle.com/#!6/585a2/1/0 - SQLFiddle dường như bị nghẹt thở khi chạy các trường hợp thử nghiệm thực tế của tôi vì vậy thay vào đó, tôi đã xây dựng bảng "trình xây dựng truy vấn trường hợp thử nghiệm" & cung cấp cho bạn 9 câu lệnh để sao chép-dán vào cửa sổ SSMS của riêng bạn để chạy (sau khi tạo lược đồ tất nhiên, tức là hàm & bảng TestStrings).
NateJ

32

Dòng mới trong T-SQL được biểu thị bằng CHAR (13) & CHAR (10) (Trả về vận chuyển + Nguồn cấp dữ liệu). Theo đó, bạn có thể tạo câu lệnh REPLACE bằng văn bản bạn muốn thay thế dòng mới bằng.

REPLACE(MyField, CHAR(13) + CHAR(10), 'something else')

9
đây không hoàn toàn giống như câu trả lời được chấp nhận; câu trả lời được chấp nhận sẽ loại bỏ mọi kết hợp của {13, 10}. điều này chỉ loại bỏ sự kết hợp cụ thể của 13 rồi 10. Nó không tạo ra sự khác biệt cho các kết thúc dòng cửa sổ, nhưng mã hóa khác sẽ bị bỏ qua ở đây.
Đồi Andrew

24

Để làm những gì hầu hết mọi người muốn, hãy tạo một trình giữ chỗ không phải là một ký tự ngắt dòng thực sự. Sau đó, bạn thực sự có thể kết hợp các phương pháp cho:

REPLACE(REPLACE(REPLACE(MyField, CHAR(13) + CHAR(10), 'something else'), CHAR(13), 'something else'), CHAR(10), 'something else')

Cách này bạn chỉ thay thế một lần. Cách tiếp cận của:

REPLACE(REPLACE(MyField, CHAR(13), ''), CHAR(10), '')

Hoạt động tuyệt vời nếu bạn chỉ muốn loại bỏ các ký tự CRLF, nhưng nếu bạn muốn giữ chỗ, chẳng hạn như
hoặc một cái gì đó, thì cách tiếp cận đầu tiên chính xác hơn một chút.


6

Nếu kiểu dữ liệu cột của bạn là ' văn bản ' thì bạn sẽ nhận được thông báo lỗi là

Msg 8116, Cấp 16, Trạng thái 1, Dòng 2 Văn bản loại dữ liệu đối số không hợp lệ cho đối số 1 của chức năng thay thế.

Trong trường hợp này, bạn cần truyền văn bản dưới dạng nvarchar và sau đó thay thế

SELECT REPLACE(REPLACE(cast(@str as nvarchar(max)), CHAR(13), ''), CHAR(10), '')

Ok, điều này có vẻ tuyệt vời. Bây giờ, điều gì sẽ xảy ra nếu thứ tôi đang cố thay thế là "! Crlf" và vâng, đó là một nhân vật không gian sau! Crlf. Điều đáng lo ngại là điều này xảy ra ở giữa chuỗi, tôi có thể thoát khỏi: CHỌN REPLACE (REPLACE (cast (@str as nvarchar (MAX)), CHAR (33), CHAR (13), CHAR (10), CHAR (32), '') hoặc tôi có văn bản này không chính xác? Chuỗi trông như thế này: cho phép kẻ tấn công từ xa bỏ qua cơ chế bảo vệ hộp cát và nhận đặc quyền thông qua một trang web được tạo thủ công được truy cập bằng Internet Explorer, Tập trung vào từ t! hat ... đó là điểm rắc rối của tôi.
bbcompent1

3

Nếu bạn gặp sự cố khi bạn chỉ muốn xóa các ký tự dấu , bạn có thể thử điều này:

WHILE EXISTS
(SELECT * FROM @ReportSet WHERE
    ASCII(right(addr_3,1)) = 10
    OR ASCII(right(addr_3,1)) = 13
    OR ASCII(right(addr_3,1)) = 32)
BEGIN
    UPDATE @ReportSet
    SET addr_3 = LEFT(addr_3,LEN(addr_3)-1)
    WHERE 
    ASCII(right(addr_3,1)) = 10
    OR ASCII(right(addr_3,1)) = 13
    OR ASCII(right(addr_3,1)) = 32
END

Điều này đã giải quyết một vấn đề tôi gặp phải với các địa chỉ trong đó một thủ tục tạo ra một trường có số dòng cố định, ngay cả khi những dòng đó trống. Để tiết kiệm không gian trong báo cáo SSRS của tôi, tôi đã cắt chúng xuống.


1

Nếu bạn có quy trình mở bằng cách sử dụng sp_helptext thì chỉ cần sao chép tất cả văn bản trong truy vấn sql mới và nhấn nút ctrl + h sử dụng biểu thức chính quy để thay thế và đặt ^ \ n vào trường tìm thay thế bằng khoảng trống. để biết thêm chi tiết kiểm tra hình ảnh. nhập mô tả hình ảnh ở đây


1

Giải pháp @Cerebrus: cho H2 cho chuỗi "+" không được hỗ trợ. Vì thế:

REPLACE(string, CHAR(13) || CHAR(10), 'replacementString')

0

Câu trả lời được đăng ở trên / trước đó đã được báo cáo để thay thế trả lại vận chuyển CHAR (13) CHAR (10):

REPLACE(REPLACE(REPLACE(MyField, CHAR(13) + CHAR(10), 'something else'), CHAR(13), 'something else'), CHAR(10), 'something else')

Sẽ không bao giờ nhận được REPLACE(MyField, CHAR(13) + CHAR(10), 'something else')phần mã và sẽ trả về kết quả không mong muốn của:

'something else''something else'

Và KHÔNG phải là kết quả mong muốn của một lần duy nhất:

'something else'

Điều đó sẽ yêu cầu kịch bản REPLACE được viết lại như sau:

REPLACE(REPLACE(REPLACE(MyField, CHAR(10), 'something else'), CHAR(13), 'something else'), CHAR(13) + CHAR(10), 'something else')

Khi luồng đầu tiên kiểm tra câu lệnh REPLACE trái thứ 1 / xa nhất, sau đó khi thất bại sẽ tiếp tục kiểm tra câu lệnh REPLACE tiếp theo.

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.