我有一个列调用Title
,我需要使用以下分隔符将其拆分为3:<BR>
。如果标题为空,我必须将三列设置为空
我使用一个填充了多行的临时表,我希望在插入临时表时分割Title
。
这是我桌子的快照:
CREATE TABLE #tempResults (
[...]
EMM_TITLE nvarchar(255),
TITLE_LINE_1 nvarchar(255),
TITLE_LINE_2 nvarchar(255),
TITLE_LINE_3 nvarchar(255))
这是我的插入请求。第EMM_TITLE
行是从数据库中检索的
INSERT INTO [#tempResults]
SELECT
[...]
'Fooooo<BR>Fooooo2<BR>Foooooo3'
'' -- Expect : Fooooo
'' -- Expect : Fooooo2
'' -- Expect : Foooooo3
如果TITLE为空,我怎么可能将列分成三列并设置为空?
我发现有关类似问题的帖子,但无法将其应用于我的案例: Link
答案 0 :(得分:2)
此分割功能可能有助于开始:
CREATE FUNCTION [dbo].[Split]
(
@RowData nvarchar(2000),
@SplitOn nvarchar(5)
)
RETURNS @RtnValue table
(
Id int identity(1,1),
Data nvarchar(100)
)
AS
BEGIN
Declare @Cnt int
Set @Cnt = 1
While (Charindex(@SplitOn,@RowData)>0)
Begin
Insert Into @RtnValue (data)
Select
Data = ltrim(rtrim(Substring(@RowData,1,Charindex(@SplitOn,@RowData)-1)))
Set @RowData = Substring(@RowData,Charindex(@SplitOn,@RowData)+len(@SplitOn),len(@RowData))
Set @Cnt = @Cnt + 1
End
Insert Into @RtnValue (data)
Select Data = ltrim(rtrim(@RowData))
Return
END
GO
您可以像以下一样使用它:
SELECT * FROM dbo.Split('Fooooo<BR>Fooooo2<BR>Foooooo3','<BR>')
......甚至更好,将它与以下功能结合使用:
CREATE FUNCTION Word
(
@Input nvarchar(max),
@Delim nvarchar(10),
@Item int
)
RETURNS nvarchar(max)
AS
BEGIN
DECLARE @result nvarchar(max)
SELECT @result = Data
FROM dbo.Split(@Input, @Delim)
WHERE Id = @Item
RETURN @Result
END
例如:
UPDATE #tempTable
SET TITLE_LINE_1 = dbo.Word(EMM_TITLE ,'<BR>',1),
TITLE_LINE_2 = dbo.Word(EMM_TITLE ,'<BR>',2),
TITLE_LINE_3 = dbo.Word(EMM_TITLE ,'<BR>',3)
答案 1 :(得分:0)
这是另一种不需要循环的方法。它比在多语句表值函数中使用循环要快得多。这项技术非常依赖于Jeff Moden和sql server central社区的精彩工作。这是我所指的文章。 http://www.sqlservercentral.com/articles/Tally+Table/72993/
if OBJECT_ID('DelimitedSplit8K_LongDelimiter') is not null
drop function DelimitedSplit8K_LongDelimiter
GO
CREATE FUNCTION [dbo].[DelimitedSplit8K_LongDelimiter]
(
@pString VARCHAR(8000)
, @pDelimiter VARCHAR(10)
)
RETURNS TABLE WITH SCHEMABINDING AS
RETURN
--===== "Inline" CTE Driven "Tally Table" produces values from 0 up to 10,000...
WITH
E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
cteTally(N) AS
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1 FROM E4
),
cteStart(N1) AS (--==== This returns N+1 (starting position of each "element" just once for each delimiter)
SELECT t.N + 1
FROM cteTally t
WHERE (SUBSTRING(@pString, t.N, DATALENGTH(@pDelimiter)) = @pDelimiter OR t.N = 0)
)
--===== Do the actual split. The ISNULL/NULLIF combo handles the length for the final element when no delimiter is found.
select ItemNumber = ROW_NUMBER() OVER(ORDER BY s.N1)
, Item = SUBSTRING(@pString, Case when s.N1 = 1 then 1 else s.N1 + (DATALENGTH(@pDelimiter) - 1) end,
ISNULL(
NULLIF(
CHARINDEX(@pDelimiter, @pString, s.N1 )
,0)
- Case when s.N1 = 1 then 1 else s.N1 + (DATALENGTH(@pDelimiter) - 1) end,8000)
)