这是恢复 67 (类型安全!!)的最简单答案:
SELECT CAST('<x>' + REPLACE('1,222,2,67,888,1111',',','</x><x>') + '</x>' AS XML).value('/x[4]','int')
在下文中,您将找到示例如何将其与字符串、分隔符和位置的变量一起使用(即使对于带有 XML 禁止字符的边缘情况)
最容易的
这个问题不是关于字符串拆分方法,而是关于如何获取第 n 个元素。最简单、完全可内联的方式是这个 IMO:
这是让第 2 部分由空格分隔的真正单行代码:
DECLARE @input NVARCHAR(100)=N'part1 part2 part3';
SELECT CAST(N'<x>' + REPLACE(@input,N' ',N'</x><x>') + N'</x>' AS XML).value('/x[2]','nvarchar(max)')
变量可以与sql:variable()
或一起使用sql:column()
当然,您可以将变量用于分隔符和位置(用于sql:column
直接从查询值中检索位置):
DECLARE @dlmt NVARCHAR(10)=N' ';
DECLARE @pos INT = 2;
SELECT CAST(N'<x>' + REPLACE(@input,@dlmt,N'</x><x>') + N'</x>' AS XML).value('/x[sql:variable("@pos")][1]','nvarchar(max)')
带有 XML 禁止字符的 Edge-Case
如果您的字符串可能包含禁止字符,您仍然可以这样做。只需FOR XML PATH
先在您的字符串上使用,以隐式地用合适的转义序列替换所有禁用字符。
如果-另外-您的分隔符是分号,这是一个非常特殊的情况。在这种情况下,我首先将分隔符替换为“#DLMT#”,最后将其替换为 XML 标记:
SET @input=N'Some <, > and &;Other äöü@€;One more';
SET @dlmt=N';';
SELECT CAST(N'<x>' + REPLACE((SELECT REPLACE(@input,@dlmt,'#DLMT#') AS [*] FOR XML PATH('')),N'#DLMT#',N'</x><x>') + N'</x>' AS XML).value('/x[sql:variable("@pos")][1]','nvarchar(max)');
SQL-Server 2016+ 的更新
遗憾的是,开发人员忘记使用STRING_SPLIT
. 但是,使用 SQL-Server 2016+,有JSON_VALUE
和OPENJSON
.
我们可以将JSON_VALUE
位置作为索引数组传递。
对于文档明确说明OPENJSON
:
当 OPENJSON 解析 JSON 数组时,该函数将 JSON 文本中元素的索引作为键返回。
像这样的字符串1,2,3
只需要括号:[1,2,3]
.
一串单词 like this is an example
need to be ["this","is","an"," example"]
。
这些是非常简单的字符串操作。试试看:
DECLARE @str VARCHAR(100)='Hello John Smith';
DECLARE @position INT = 2;
--We can build the json-path '$[1]' using CONCAT
SELECT JSON_VALUE('["' + REPLACE(@str,' ','","') + '"]',CONCAT('$[',@position-1,']'));
--查看这个位置安全的字符串拆分器(从零开始):
SELECT JsonArray.[key] AS [Position]
,JsonArray.[value] AS [Part]
FROM OPENJSON('["' + REPLACE(@str,' ','","') + '"]') JsonArray
在这篇文章中,我测试了各种方法,发现OPENJSON
速度非常快。甚至比著名的“delimitedSplit8k()”方法还要快...
更新 2 - 获取类型安全的值
我们可以简单地通过使用 doubled 来在数组中[[]]
使用数组。这允许一个类型化的WITH
子句:
DECLARE @SomeDelimitedString VARCHAR(100)='part1|1|20190920';
DECLARE @JsonArray NVARCHAR(MAX)=CONCAT('[["',REPLACE(@SomeDelimitedString,'|','","'),'"]]');
SELECT @SomeDelimitedString AS TheOriginal
,@JsonArray AS TransformedToJSON
,ValuesFromTheArray.*
FROM OPENJSON(@JsonArray)
WITH(TheFirstFragment VARCHAR(100) '$[0]'
,TheSecondFragment INT '$[1]'
,TheThirdFragment DATE '$[2]') ValuesFromTheArray