【问题标题】:SQL Split functionSQL 拆分函数
【发布时间】:2010-05-20 09:11:23
【问题描述】:

我正在寻找一种方法来做到这一点......

SELECT FirstName, LastName, Split(AddressBlock, '  ', 1), Split(AddressBlock, ' ', 2), PostCode 
FROM Contacts

我要传递的参数是...

  1. 地址
  2. 分隔符(当前情况需要 2 个空格,但这可能是逗号或空格后跟逗号)或其他内容(会有所不同)。
  3. 我要返回的地址部分(我并不总是需要拆分结果的所有部分)。

我似乎能够在互联网上找到一些拆分函数的示例,但它们返回一个包含整个拆分部分集的表格。

我的 SQL 技能不是很好,所以我需要非常简单的答案。 我一直在使用 nvarchar 数据,并且该函数需要可重用。

【问题讨论】:

  • 我不同意,因为我只想提取 plist 结果的某些部分而不希望检索表变量。每次调用函数时我都想要一个字符串。但是,那里有一个解决方案,可能是一个好的开始。

标签: sql tsql function split


【解决方案1】:

如果您想要一个用户定义的函数来执行此操作,这应该可以。不是很漂亮,但是...

CREATE FUNCTION dbo.SplitStringPart (
    @input nvarchar(MAX),
    @separator nvarchar(10),
    @index int
) RETURNS nvarchar(MAX)
BEGIN

DECLARE @counter int,
        @position int,
        @oldposition int,
        @separatorlength int,
        @result nvarchar(MAX)

SET @separatorlength = DATALENGTH(@separator) / 2
IF @separatorlength = 0 RETURN NULL

SET @result = NULL

SET @counter = 1
SET @position = -2

WHILE (@counter <= @index)
BEGIN

    SET @oldposition = @position
    SET @position = CHARINDEX(@separator, @input, @position + 1)
    IF @position = 0 AND @counter < @index
    BEGIN
        SET @oldposition = 0
        BREAK
    END
    SET @counter = @counter + 1

END

IF @oldposition = 0 AND @position = 0
    RETURN NULL
ELSE IF @oldposition < 0
BEGIN
    IF @position = 0 AND @index = 1
        SET @result = @input
    ELSE
        SET @result = SUBSTRING(@input, 0, @position)
END
ELSE IF @position <= 0
    SET @result = SUBSTRING(@input, @oldposition + @separatorlength, LEN(@input) - @oldposition - @separatorlength)
ELSE
    SET @result = SUBSTRING(@input, @oldposition + @separatorlength, @position - @oldposition - @separatorlength)

RETURN @result

END
GO

【讨论】:

  • 当字符串只有 1 部分并且我要求第 2 部分时它确实会中断......虽然不理想。
【解决方案2】:

这不是很漂亮,但是将它添加到您的 SQL 语句中,它应该可以工作:

CASE 
WHEN charindex(' ', substring(AddressBlock, (charindex(' ', AddressBlock) + 1), len(AddressBlock))) > 0 THEN substring(AddressBlock, (charindex(' ', AddressBlock) + 1), charindex(' ', substring(AddressBlock, (charindex(' ', AddressBlock) + 1), len(AddressBlock))) - 1)
ELSE substring(AddressBlock, (charindex(' ', AddressBlock) + 1), len(AddressBlock))    
END AS 'Address 1', 
CASE WHEN charindex(' ', substring(AddressBlock, (charindex(' ', AddressBlock) + 1), len(AddressBlock))) > 0 THEN substring(AddressBlock, charindex(' ', AddressBlock) + charindex(' ', substring(AddressBlock, (charindex(' ', AddressBlock) + 1), len(AddressBlock))) + 1, Len(AddressBlock))
ELSE ''
END AS 'Address 2'

【讨论】:

  • 这不是寻找一个单独的字符来执行拆分吗?我需要拆分一个字符串值(例如“,”)......虽然很有趣......
  • 这会在现有列中查找字符串值,并剔除所有字符串值。因此,如果您想用逗号分隔,请将 charindex(' ' 更改为 charindex(','。
  • 这不是我所要求的,而是一个很好的努力,所以你得到了我的投票:)
【解决方案3】:

这是我的答案版本。这更快更健壮。无需为子字符串、字符索引等大惊小怪。

CREATE FUNCTION [dbo].[SplitArray]
(
    @RowToSplit nvarchar(MAX),
    @Delimeter nvarchar(MAX)
)  
RETURNS @RtnValue table (ID bigint IDENTITY, Data nvarchar(MAX)) 
AS  
BEGIN 
    DECLARE @xml xml
    SET @xml = '<field>' + REPLACE(@RowToSplit, @Delimeter, '</field><field>') + '</field>'
    INSERT INTO @RtnValue(data)
    SELECT  tbl.c.value('.','nvarchar(max)')
    FROM @xml.nodes('/field') tbl(c)
    RETURN
END

您只需在表中使用生成的拆分值,如下所示:

SELECT Data FROM dbo.SplitArray('this is great',' ')

这将返回:

Data
============
this
is
great

【讨论】:

  • 所以让我做对了...要获得一段字符串,您将其拆分,然后构建一个更大的 xml 字符串,然后解析该 xml,然后查询它,sql 将执行此操作更快......如果这是真的,这是多么奇怪的技术 SQL!
  • xml 是一个二进制对象,所以不太正确。用查询分析器运行它,你会看到。字符索引很慢,因为它是基于字符串的,使用 xml 它是基于二进制的。
猜你喜欢
  • 2019-01-21
  • 1970-01-01
  • 1970-01-01
  • 2013-10-13
  • 2010-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多