在TSQL中替换换行符


414

我想替换(或删除)TSQL字符串中的换行符。有任何想法吗?

明显的

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

只是不会做...

Answers:


841

实际上,SQL命令或脚本字符串中的新行可以是CR,LF或CR + LF中的任何一行。为了获得全部,您需要这样的东西:

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

5
@NielsBrinch只要它是字符串中唯一的换行符,就可以正常工作。但是SQL Server确实支持所有三种类型。实际上,如果您曾经提取所有系统存储过程和脚本视图,则可以找到Microsoft自己使用的所有三个实例。
RBarryYoung

在进行此更改副本和粘贴列数据之前,这对我b / c来说是有效的,这将使光标位于文本末尾的两个空格。进行此更改后,将复制和粘贴到记事本中的光标直接位于文本的末尾。这对我的前端GUI中的b / c造成了问题,新行char出现了。
natur3 2015年

8
如果列数据类型是文本,则需要先强制转换为nvarchar,然后替换SELECT REPLACE(REPLACE(cast(@str as nvarchar(max)),CHAR(13),''),CHAR(10),'')
2013年

1
@Slint是的,很好。实际上,要从客户端代码使用此名称,您应该添加一个列名。尽管确实有很多次您可以.columns[0]代替使用。
RBarryYoung

2
对于我使用的Oracle版本,该语句为CHR,而不是CHAR。万一有人试图从Oracle进行调试,以防万一。否则,其他所有条件均适用。
塞多纳

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

2
这是我首先尝试的方法,但是对于所有数据它都无法可靠地工作。@RBarryYoung在上面。
Mark W Dickson's

1
谢谢,我不得不对此稍作修改,对我来说,它是:replace(REPLACE(@string,CHAR(13),''),CHAR(10),'')
user734028

36

我参加聚会可能晚了一年,但是我每天都在处理查询和MS-SQL,并且我对内置函数LTRIM()和RTRIM()感到厌倦(并且总是不得不一起调用它们),并且由于没有捕获到最后有换行符的“脏”数据,因此我认为是时候实现一个更好的TRIM功能了。欢迎同仁反馈!

免责声明:实际上,这消除了(用单个空格代替)空格的扩展形式(制表符,换行,回车等),因此从我的原始答案中将其重命名为“ CleanAndTrim”。这里的想法是,你的字符串并不需要它里面这种额外的特殊空白字符,所以如果在头/尾不发生他们,他们应该用简单的空间所取代。如果您有意将这样的字符存储在字符串中(例如,要在其上运行的数据列),请不要这样做!改进此功能或编写自己的函数,即从字串的端点而不是从“ body”中删除这些字符。

好的,既然免责声明已经更新,下面是代码。

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

干杯!

另一个免责声明:您的典型Windows换行符是CR + LF,因此,如果您的字符串包含那些,则最终将其替换为“双”空格。

2016年更新:一个新版本,使您可以选择用其他所选字符替换那些特殊空格字符!这还包括注释和Windows CR + LF配对的解决方法,即用单个替换替换该特定的字符对。

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

过去的用户,请注意更改和免责声明-对于使用和用途的初步假设,我深表歉意。
NateJ

1
新更新!可以在这里找到测试用例sqlfiddle.com /# ! 6 /585a2 /1/ 0 -SQLFiddle似乎在我的实际测试用例中阻塞了,因此,我建立了一个“测试用例查询生成器”表&为您提供9条语句,以便将其复制粘贴到您自己的SSMS窗口中以运行(当然要创建模式,即函数和TestStrings表之后)。
NateJ

32

T-SQL中的换行符由CHAR(13)和CHAR(10)(回车+换行符)表示。因此,您可以使用要替换换行符的文本创建一个REPLACE语句。

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

9
这与接受的答案并不完全相同;接受的答案将删除{13,10}的任何组合。这只会删除13到10的特定组合。它不会对Windows行尾产生差异,但此处会漏掉其他编码。
Andrew Hill

24

要执行大多数人想要的操作,请创建一个不是实际换行符的占位符。然后,您可以实际结合以下方法:

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

这样,您只需更换一次。的方法:

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

如果只想摆脱CRLF字符,效果很好,但是如果要使用占位符(例如
或诸如此类),则第一种方法会更准确一些。


6

如果您的列数据类型为' text ',则您将收到一条错误消息,提示为

消息8116,级别16,状态1,第2行参数数据类型的文本对于替换功能的参数1无效。

在这种情况下,您需要将文本转换为nvarchar,然后替换

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

好的,这看起来很棒。现在,如果我要替换的是“!crlf”,可以,那是!crlf之后的空格字符。值得关注的是,这发生在字符串的中间,我可以摆脱:SELECT REPLACE(REPLACE(cast(@str as nvarchar(MAX)),CHAR(33),CHAR(13),CHAR(10),CHAR (32),'')还是我写的不正确?字符串如下所示:允许远程攻击者绕过沙盒保护机制并通过精心制作的网站获得特权t!使用Internet Explorer访问hat t!帽子这个词...这是我的麻烦所在
bbcompent1

3

如果您只想删除结尾字符,则可以尝试以下操作:

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

这解决了我遇到的一个地址问题,其中一个过程创建了一个具有固定行数的字段,即使这些行为空。为了节省SSRS报告中的空间,我将其缩减。


1

如果您具有使用sp_helptext的开放过程,则只需在新的sql查询中复制所有文本,然后按ctrl + h按钮,使用正则表达式进行替换,并将^ \ n放在find字段中,并用blank替换。有关更多详细信息,请检查图像。在此处输入图片说明


1

到@Cerebrus解决方案:对于H2,不支持字符串“ +”。所以:

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

0

上面/之前发布的答案被报告为替换CHAR(13)CHAR(10)回车:

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

永远不会到达REPLACE(MyField, CHAR(13) + CHAR(10), 'something else')代码的那一部分,并且将返回以下有害结果:

'something else''something else'

而不是单个结果:

'something else'

这将需要将REPLACE脚本重写为:

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

当流程首先测试第一个/最左边的REPLACE语句时,然后在失败时将继续测试下一个REPLACE语句。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.