编辑:允许多个字符分隔符
这就是我解决它的方法,使用两个函数来拆分成列(如果您还想要一个更完整的行拆分解决方案,see my other post here)。它涉及:
- 一个标量函数 (
fSubstrNth),用于在给定分隔符的情况下提取一行的第 n 个字段
- 用于查找分隔符的第 n 个索引的标量函数 (
fPatIndexMulti)
- (可选)替代
Right 函数以接受负值
- 最后,在您的解决方案中使用一些特定代码,因为 SQL 不允许动态表函数定义(换句话说,您不能从具有动态列的函数中
SELECT)
现在,对于代码 sn-ps:
fSubstrNth
-- =============================================
-- Author: Bernardo A. Dal Corno
-- Create date: 18/07/2017
-- Description: substring com 2 PatIndex limitando inicio e fim
-- =============================================
CREATE FUNCTION fSubstrNth
(
@Text varchar(max),
@Sep varchar(3),
@N int --Nth campo
)
RETURNS varchar(max)
AS
BEGIN
DECLARE @Result varchar(max)
IF @N<1 RETURN ''
IF @N=1
SET @Result = substring(@Text, 1, dbo.fPatIndexMulti(@Sep,@Text,1)-1)
ELSE
SET @Result = substring(@Text, dbo.fPatIndexMulti(@Sep,@Text,@N-1)+LEN(@Sep), CASE WHEN dbo.fPatIndexMulti(@Sep,@Text,@N)>0 THEN dbo.fPatIndexMulti(@Sep,@Text,@N)-dbo.fPatIndexMulti(@Sep,@Text,@N-1)-LEN(@Sep) ELSE LEN(@Text)+1 END)
RETURN @Result
END
fPatIndexMulti
-- =============================================
-- Author: Bernardo A. Dal Corno
-- Create date: 17/07/2017
-- Description: recursive patIndex
-- =============================================
CREATE FUNCTION [dbo].[fPatIndexMulti]
(
@Find varchar(max),
@In varchar(max),
@N tinyint
)
RETURNS int
AS
BEGIN
DECLARE @lenFind int, @Result int, @Texto varchar(max), @index int
DECLARE @i tinyint=1
SET @lenFind = LEN(@Find)-1
SET @Result = 0
SET @Texto = @In
WHILE (@i <= @N) BEGIN
SET @index = patindex('%'+@Find+'%',@Texto)
IF @index = 0 RETURN 0
SET @Result = @Result + @index
SET @Texto = dbo.xRight(@Texto, (@index + @lenFind)*-1)
SET @i = @i + 1
END
SET @Result = @Result + @lenFind*(@i-2)
RETURN @Result
END
xRight
-- =============================================
-- Author: Bernardo A. Dal Corno
-- Create date: 06/01/2015
-- Description: Right inverso (para nros < 0)
-- =============================================
CREATE FUNCTION [dbo].[xRight]
(
@Texto varchar(8000),
@Qntd int
)
RETURNS varchar(8000)
AS
BEGIN
DECLARE @Result varchar(8000)
IF (Len(@Texto) = 0) OR (@Qntd = 0)
SET @Result = ''
ELSE IF (@Qntd > 0)
SET @Result = Right(@Texto, @Qntd)
ELSE IF (@Qntd < 0)
SET @Result = Right(@Texto, Len(@Texto) + @Qntd)
RETURN @Result
END
具体代码
SELECT
acolumn = 'any value',
field1 = dbo.fSubstrNth(table.datacolumn,',',1),
field2 = dbo.fSubstrNth(table.datacolumn,',',2),
anothercolumn = 'set your query as you would normally do',
field3 = (CASE dbo.fSubstrNth(table.datacolumn,',',3) WHEN 'C' THEN 1 ELSE 0 END)
FROM table
注意:
-
fSubstrNth 接收要从“数据列”中提取的第 n 个字段
- 查询可以是任何其他查询。这意味着它可以存储在过程、表格函数、视图等中。您可以按您希望的任何顺序提取部分或全部字段,并按您的意愿进行处理
- 如果在存储过程中使用,您可以创建一个通用的方法来创建一个查询和临时表来加载带有动态列的字符串,但是您必须调用另一个过程来使用数据或创建一个特定的查询像上面一样在相同的过程中(这将使它成为非通用的,只是更可重用)