我在使用T-SQL时遇到了困难,我想知道是否有人能让我指出正确的方向。 我有以下变量叫做@input
DECLARE @input nvarchar(100);
SET @input= '27364 - John Smith';
-- SET @input= '27364 - John Andrew Smith';
如果字符串包含MiddleName,我需要将此字符串拆分为3个部分(ID,Firstname和LastName)或4。出于安全原因,我无法使用功能。
我的aproach是使用Substring和Charindex。
SET @Id = SUBSTRING(@input, 1, CASE CHARINDEX('-', @input)
WHEN 0
THEN LEN(@input)
ELSE
CHARINDEX('-', @input) - 2
END);
SET @FirstName = SUBSTRING(@input, CASE CHARINDEX(' ', @input)
WHEN 0
THEN LEN(@input) + 1
ELSE
CHARINDEX(' ', @input) + 1
END, 1000);
SET @LastName = SUBSTRING(@input, CASE CHARINDEX(' ', @input)
WHEN 0
THEN LEN(@input) + 1
ELSE
CHARINDEX('0', @input) + 1
END, 1000);
Select @PartyCode,@FirstName,@LastName
我被困了,因为我不知道如何继续进行,而且如果Middlename存在,代码必须足够聪明才能添加第四个分割。
有什么想法吗?
提前致谢
答案 0 :(得分:3)
希望这是规范化项目的一部分。这个数据打破1NF,其中一个真的应该避免......
尝试这样
优点
如果您愿意,可以使用CASE WHEN
检查最后一部分是NULL
,并在这种情况下将Part2放入Part3 ......
DECLARE @input table(teststring nvarchar(100));
INSERT INTO @input VALUES
(N'27364 - John Smith'),(N'27364 - John Andrew Smith');
WITH Splitted AS
(
SELECT CAST(N'<x>' + REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(teststring,N' - ',N' '),N'&',N'&'),N'<',N'<'),N'>',N'>'),N' ',N'</x><x>') + N'</x>' AS XML) testXML
FROM @input
)
SELECT testXML.value('/x[1]','int') AS Number
,testXML.value('/x[2]','nvarchar(max)') AS Part1
,testXML.value('/x[3]','nvarchar(max)') AS Part2
,testXML.value('/x[4]','nvarchar(max)') AS Part3
FROM Splitted
结果
Number Part1 Part2 Part3
27364 John Smith NULL
27364 John Andrew Smith
答案 1 :(得分:0)
SQL Server 2016有一个名为STRING_SPLIT()
的新内置函数假设创建内置函数,但不允许使用CLR函数:
% Set up parameters
nT = 200; N = 50; w = 0.05;
% Set up results matrix, including initial conditions by row 1 (all 0)
d = zeros(nT, N);
% Loop, storing results to d
for t = 2:nT
d(t,:) = d(t-1,:) + w*rand(1,N);
end
用法:
CREATE FUNCTION dbo.WORD_SPLIT
(
@String AS nvarchar(4000)
)
RETURNS TABLE
AS
RETURN
(
WITH Spaces AS
(
SELECT Spaced.[value], ROW_NUMBER() OVER (PARTITION BY 1 ORDER BY (SELECT 1)) AS ordinal
FROM STRING_SPLIT(@String, ' ') AS Spaced
)
, Tabs AS
(
SELECT Tabbed.[value], ROW_NUMBER() OVER (PARTITION BY 1 ORDER BY s.ordinal, (SELECT 1)) AS ordinal
FROM Spaces AS s
CROSS APPLY STRING_SPLIT(s.[value], ' ') AS Tabbed
)
, NewLines1 AS
(
SELECT NewLined1.[value], ROW_NUMBER() OVER (PARTITION BY 1 ORDER BY t.ordinal, (SELECT 1)) AS ordinal
FROM Tabs AS t
CROSS APPLY STRING_SPLIT(t.[value], CHAR(13)) AS NewLined1
)
, NewLines2 AS
(
SELECT NewLined2.[value], ROW_NUMBER() OVER (PARTITION BY 1 ORDER BY nl1.ordinal, (SELECT 1)) AS ordinal
FROM NewLines1 AS nl1
CROSS APPLY STRING_SPLIT(nl1.[value], CHAR(10)) AS NewLined2
)
SELECT LTRIM(RTRIM(nl2.[value])) AS [value], ROW_NUMBER() OVER (PARTITION BY 1 ORDER BY nl2.ordinal, (SELECT 1)) AS ordinal
FROM NewLines2 AS nl2
WHERE LTRIM(RTRIM(nl2.[value])) <> ''
)
GO
或者假设,根据安全性,您不允许进行架构更改:
-- Not Normailized
SELECT i.*, split.[value], split.[ordinal]
FROM @input AS i
CROSS APPLY dbo.WORD_SPLIT(i.teststring) AS split
-- Normalized
;WITH Splitted AS
(
SELECT split.[value], split.[ordinal]
FROM @input AS i
CROSS APPLY dbo.WORD_SPLIT(i.teststring) AS split
)
SELECT *
FROM (SELECT [value], 'part' + CONVERT(nvarchar(20), [ordinal]) AS [parts] FROM Splitted) AS s
PIVOT (MAX([value]) FOR [parts] IN ([part1], [part2], [part3], [part4])
希望有帮助!