STRING_SPLIT 带有多字符分隔符?

Pet*_*din 11 sql-server t-sql sql-server-2016 string-manipulation

SQL Server 2016 引入了STRING_SPLIT,它非常快,是人们在 2016 年之前推出的任何自制实现的绝佳替代品。

不幸的是,STRING_SPLIT 只支持单字符分隔符,这并不总是足够的。有谁知道允许在分隔符中使用多个字符的良好实现?

Aar*_*and 24

好吧,您总是可以REPLACE在传入参数之前使用单字符分隔符添加它。您只需要选择一个不太可能/不可能出现在实际数据中的字符。在这个例子中,假设您的原始数据使用三个管道作为分隔符;我随机选择了一个 Unicode 字符来替换:

DECLARE 
  @olddelim nvarchar(32) = N'|||', 
  @newdelim nchar(1)     = NCHAR(9999); -- pencil (?)

DECLARE @x nvarchar(max) = N'foo|||bar|||blat|||splunge';

SELECT * FROM STRING_SPLIT(REPLACE(@x, @olddelim, @newdelim), @newdelim);
Run Code Online (Sandbox Code Playgroud)

我在博客上更详细地介绍了这一点:


处理评论:

不好的解决方案。如果原始字符串类似于 'abc||pqr|||rst||123' (动态并且可以包含任何内容)会怎样。所需的 o/p 是 'abc||pqr' 和 'rst||123' 但您的解决方案将给出 'abc' 'pqr' 'rst' '123'

好的,让我们接受您的输入,看看我的解决方案是否得到错误的输出。

DECLARE 
  @olddelim nvarchar(32) = N'|||', 
  @newdelim nchar(1)     = NCHAR(9999); -- pencil (?)

DECLARE @x nvarchar(max) = N'abc||pqr|||rst||123';

SELECT * FROM STRING_SPLIT(REPLACE(@x, @olddelim, @newdelim), @newdelim);
Run Code Online (Sandbox Code Playgroud)

结果是:

abc||pqr
rst||123
Run Code Online (Sandbox Code Playgroud)

而不是你必须假设(但没有测试)这个:

abc
pqr
rst
123
Run Code Online (Sandbox Code Playgroud)

如果您的数据在表中,您可以创建一个视图,这样您就不必将该表达式考虑到您的所有查询中。


如果这不起作用,因为您的数据中可能有铅笔 ( ?),并且您在1,111,998 个可用的 Unicode 字符中找不到一个不会出现在您的数据集中的字符,您将不得不跳过STRING_SPLIT(),因为它被硬编码为接受单个字符分隔符 ( separator Is a single character expression)。

替代方案之前已经在这里回答了几十次,很多之前STRING_SPLIT()已经存在。这些方法仍然有效。

STRING_SPLIT()在本系列中,我讨论了许多替代方案,并讨论了, 中的限制(我还讨论了为什么您可能会考虑不使用任何方法在 T-SQL 中执行此操作):

  • @JitendraPancholi 你_技术上_是正确的,但你在这里不公平,因为:**1)** 限制是`STRING_SPLIT`,不是这个特殊的解决方法,**2)** 这个问题是关于`STRING_SPLIT` ,一般不使用多字符分隔符,**3)** 在实践中,可以安全地假设某些字符不会出现,否则它只是坏数据,**4)** `NCHAR(31) `(记录分隔符)应该是安全的,因为这是它的目的,或者`NCHAR(0)` 和`, @newdelim COLLATE Latin1_General_100_BIN2);` 因为如果 U+0000 (null) 在任何字符串数据中,那么就会有更大的问题! (5认同)