【问题标题】:What's a good way to trim all whitespace characters from a string in T-SQL without UDF and without CLR?在没有 UDF 和 CLR 的情况下,从 T-SQL 中的字符串中修剪所有空白字符的好方法是什么?
【发布时间】:2016-02-06 20:02:16
【问题描述】:

.NET 函数 string.Trim trims a rather extensive set of whitespace characters。如何以 T-SQL 的最佳方式模拟这种确切的行为?

LTRIMRTRIM 只修剪不够的空格字符。

使用 SQL CLR 很容易做到这一点,但这并不总是可行的,而且调用成本也很高。所以我想避免使用 SQL CLR。​​

此外,标量 UDF 会强制执行串行计划并且调用速度很慢。所以它可能也不应该是一个标量 UDF。

鉴于这些限制,最好的方法是什么?

【问题讨论】:

  • 您能给我们举个例子,说明您想要的输出是什么?如果你有这样的字符串:' toto tata ',你想要这样的'tototata' 吗?
  • 您只想修剪字符串末尾的空格,而不是字符串内的空格?例如,您不想用单个空格替换字符串中的多个制表符或完全删除它们。
  • 我想要 string.Trim 输出的内容,即删除前导和尾随空格。
  • 我已更新我的答案以包含 .NET Framework 4 空白字符并进行左、右和双端修剪。 (LEN 与尾随空白功能让我转了一圈。)
  • 好的,现在它已经更新为“Hello world!”例如,处理 NULL、空字符串、所有空白字符串,...。没有尝试从右到左的文本。仍在轨道上。

标签: .net sql-server tsql


【解决方案1】:

此代码提供了一种模式,您可以扩展该模式以处理您为修改后的LTRIM 选择的空格。

declare @Tab as NVarChar(1) = NChar( 9 );
declare @Space as NVarChar(1) = NChar( 32 );

declare @Samples as Table ( String NVarChar(16) );
insert into @Samples ( String ) values
  ( 'Foo' ),
  ( @Tab + 'Foo' ),
  ( @Space + 'Foo' ),
  ( @Space + @Tab + 'Foo' ),
  ( @Tab + @Space + 'Foo' );
select String, Len( String ) as [Length], PatIndex( '%[^' + @Tab + @Space + ']%', String ) - 1 as [WhitespaceCount]
  from @Samples;

REVERSE 函数可用于实现RTRIM 的修改版本。

较新的更新: 以下代码使用 .NET Framework 4 中使用的空白字符列表。它也适用于 LEN功能,不包括尾随空格。

declare @Tab as NVarChar(1) = NChar( 9 );
declare @Space as NVarChar(1) = NChar( 32 );

declare @Samples as Table ( String NVarChar(16) );
insert into @Samples ( String ) values
  ( 'Foo' ),
  ( @Tab + 'Foo' ),
  ( @Space + 'Foo' ),
  ( @Space + @Tab + 'Foo' ),
  ( @Tab + @Space + 'Foo' ),
  ( @Tab + 'Foo' + @Space ),
  ( @Space + 'Foo' + @Tab ),
  ( @Space + @Tab + 'Foo' + @Tab + @Space ),
  ( @Tab + @Space + 'Foo' + @Space + @Tab ),
  ( 'Foo' + @Tab ),
  ( NULL ),
  ( '           ' ),
  ( @Space + NULL + @Tab + @Tab ),
  ( '' ),
  ( 'Hello world!' );

declare @WhitespacePattern as NVarChar(100) = N'%[^' +
  NChar( 0x0020 ) + NChar( 0x00A0 ) + NChar( 0x1680 ) + NChar( 0x2000 ) +
  NChar( 0x2001 ) + NChar( 0x2002 ) + NChar( 0x2003 ) + NChar( 0x2004 ) +
  NChar( 0x2005 ) + NChar( 0x2006 ) + NChar( 0x2007 ) + NChar( 0x2008 ) +
  NChar( 0x2009 ) + NChar( 0x200A ) + NChar( 0x202F ) + NChar( 0x205F ) +
  NChar( 0x3000 ) + NChar( 0x2028 ) + NChar( 0x2029 ) + NChar( 0x0009 ) +
  NChar( 0x000A ) + NChar( 0x000B ) + NChar( 0x000C ) + NChar( 0x000D ) +
  NChar( 0x0085 ) + N']%';
-- NB: The   Len   function does not count trailing spaces.
--     Use   DataLength   instead.
with AnalyzedSamples as (
  select String, DataLength( String ) / DataLength( NChar( 42 ) ) as [StringLength],
    PatIndex( @WhitespacePattern, String ) - 1 as [LeftWhitespace],
    PatIndex( @WhitespacePattern, Reverse( String ) ) - 1 as [RightWhitespace]
  from @Samples ),
  TrimmedSamples as (
  select String, StringLength, [LeftWhitespace], [RightWhitespace],
    case
      when String is NULL then NULL
      when LeftWhitespace = -1 then N''
      else Substring( String, LeftWhitespace + 1, StringLength - LeftWhitespace )
      end as [LTrim],
    case
      when String is NULL then NULL
      when RightWhitespace = -1 then N''
      else Reverse( Substring( Reverse( String ), RightWhitespace + 1, StringLength - RightWhitespace ) )
      end as [RTrim],
    case
      when String is NULL then NULL
      when LeftWhitespace = -1 then N''
      else Substring( String, LeftWhitespace + 1, StringLength - LeftWhitespace - RightWhitespace )
      end as [Trim]
    from AnalyzedSamples )
  select N'"' + String + N'"' as [String], StringLength, [LeftWhitespace], [RightWhitespace],
    N'"' + [LTrim] + N'"' as [LTrim], DataLength( [LTRIM] ) / DataLength( NChar( 42 ) ) as [LTrimLength],
    N'"' + [RTrim] + N'"' as [RTrim], DataLength( [RTRIM] ) / DataLength( NChar( 42 ) ) as [RTrimLength],
    N'"' + [Trim] + N'"' as [Trim], DataLength( [TRIM] ) / DataLength( NChar( 42 ) ) as [TrimLength]
    from TrimmedSamples;

【讨论】:

  • 很棒的答案。您可能希望为纯空白字符串添加测试用例,并且可能为中间带有空白“洞”的字符串添加测试用例。无论如何,这有望被接受:)
【解决方案2】:

我有兴趣看看是否有人找到通用 SQL 解决方案。

我能想到的最好的方法是一个简单的 REPLACE 函数:

SELECT MyString = LEFT(MyString, LEN(RTRIM(REPLACE(REPLACE(REPLACE(MyString COLLATE Latin1_General_100_BIN2, NCHAR(9), ' '), NCHAR(12), ' '), NCHAR(13), ' ')))) AS RTrimmed

SELECT MyString = RIGHT(MyString, LEN(LTRIM(REPLACE(REPLACE(REPLACE(MyString COLLATE Latin1_General_100_BIN2, NCHAR(9), ' '), NCHAR(12), ' '), NCHAR(13), ' ')))) AS LTrimmed

等等

您可以在此处获取当前空白字符的列表:

http://unicode.org/charts/uca/chart_Whitespace.html

或者,为了向自己证明这一点,您可以将所有字符的列表从 SQL Server 导出到 Excel 之类的文件中,清理字符,然后将它们重新导入。删除的都是空格。

【讨论】:

  • 这将删除字符串中间的空格。
  • 鉴于我使用的替换数量,我可以看到您的想法。它与@HABO 的示例相同,但我认为他更简洁。
猜你喜欢
  • 2021-01-20
  • 2012-03-21
  • 1970-01-01
  • 2022-11-01
  • 2015-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多