拆分sql server中的字符串

时间:2014-01-29 10:42:56

标签: sql-server database string

我在数据库中有一个逗号分隔的字符串。就像 “苹果,香蕉,菠萝,葡萄” 我需要在逗号的基础上拆分这个字符串并遍历这个。因为在sql server中没有内置函数,是否有任何有效的方法可以实现这个目标。

4 个答案:

答案 0 :(得分:25)

尝试此功能

CREATE FUNCTION [dbo].[func_Split] 
    (   
    @DelimitedString    varchar(8000),
    @Delimiter              varchar(100) 
    )
RETURNS @tblArray TABLE
    (
    ElementID   int IDENTITY(1,1),  -- Array index
    Element     varchar(1000)               -- Array element contents
    )
AS
BEGIN

    -- Local Variable Declarations
    -- ---------------------------
    DECLARE @Index      smallint,
                    @Start      smallint,
                    @DelSize    smallint

    SET @DelSize = LEN(@Delimiter)

    -- Loop through source string and add elements to destination table array
    -- ----------------------------------------------------------------------
    WHILE LEN(@DelimitedString) > 0
    BEGIN

        SET @Index = CHARINDEX(@Delimiter, @DelimitedString)

        IF @Index = 0
            BEGIN

                INSERT INTO
                    @tblArray 
                    (Element)
                VALUES
                    (LTRIM(RTRIM(@DelimitedString)))

                BREAK
            END
        ELSE
            BEGIN

                INSERT INTO
                    @tblArray 
                    (Element)
                VALUES
                    (LTRIM(RTRIM(SUBSTRING(@DelimitedString, 1,@Index - 1))))

                SET @Start = @Index + @DelSize
                SET @DelimitedString = SUBSTRING(@DelimitedString, @Start , LEN(@DelimitedString) - @Start + 1)

            END
    END

    RETURN
END

示例用法 - 只需将逗号分隔的字符串以及所需的分隔符传递给函数。

DECLARE @SQLStr varchar(100)
SELECT @SQLStr = 'Mickey Mouse, Goofy, Donald Duck, Pluto, Minnie Mouse'

SELECT
    *
FROM
    dbo.func_split(@SQLStr, ',')

结果将是这样的

Result

答案 1 :(得分:15)

  

...由于sql server中没有内置函数...

当您提出此问题时,情况确实如此,但SQL Server 2016引入了STRING_SPLIT

所以你可以使用

SELECT value
FROM   STRING_SPLIT ('apple,banana,pineapple,grapes', ',') 

存在一些限制(仅接受单个字符分隔符,并且缺少任何指示拆分索引最引人注目的列)。性能测试的各种限制和一些有希望的结果都在this blog post by Aaron Bertrand

答案 2 :(得分:6)

您可以将数据转换为XML,方法是将逗号替换为自定义标记,在本例中为<w>替换为单词。

create table t(col varchar(255));
insert into t values ('apple,banana,pineapple,grapes');
insert into t values ('car,bike,airplane');

select cast(('<w>' + replace(col, ',', '</w><w>') + '</w>') as xml) as xmlValue
  from t

返回

|                                               XMLVALUE |
|--------------------------------------------------------|
| <w>apple</w><w>banana</w><w>pineapple</w><w>grapes</w> |
|                   <w>car</w><w>bike</w><w>airplane</w> |

现在,如果您将此查询用作内部xml选择,则外部查询可以将其拆分为不同的行:

<强>解决方案:

select split.xmlTable.value('.', 'varchar(255)') as xmlValue
from (

   select cast(('<w>' + replace(col, ',', '</w><w>') + '</w>') as xml) as xmlValue
     from t

) as xmlTable
cross apply xmlValue.nodes ('/w') as split(xmlTable);

Live sqlFiddle

答案 3 :(得分:0)

我有如下使用递归的解决方案

local player = game.Players.LocalPlayer
local mouse = player:GetMouse()
local tool = script.Parent

--Creaets a text label with the text Block Ready! on it when the player 
local function onEquip()
  print("screengui1")
  local screenGui = Instance.new("ScreenGui")
  screenGui.Parent = player.PlayerGui
  local textLabel = Instance.new("TextLabel")
  textLabel.Parent = screenGui
  textLabel.BackgroundTransparency = 0.85
  textLabel.Position = UDim2.new(0, 1100, 0, 550)
  textLabel.Size = UDim2.new(0, 150, 0, 50)
  textLabel.BackgroundColor3 = BrickColor.White().Color
  textLabel.Text = "Block ready!"
end

local isGunOnCooldown = false
local cooldownTime = 3 --seconds
mouse.Button1Down:Connect(function()
    -- debounce clicks so the text dont changes (its cooldown is the same as the gun cooldown the GUI is within)
    if isGunOnCooldown then
        return
    end

    -- change the text, 
    isGunOnCooldown = true
    player.PlayerGui.ScreenGui.TextLabel.Text = "Reloading..."
    -- start the cooldown and reset it along with the test
    spawn(function()
        wait(cooldownTime)
        isGunOnCooldown = false
        player.PlayerGui.ScreenGui.TextLabel.Text = "Block ready!"
    end)
end)



local function onUnequip()
    --code to delete the gui goes here
end
tool.Equipped:connect(onEquip)
tool.Unequipped:connect(onUnequip)

您可以调用此功能

Create function split_string(@str as nvarchar(max),@separator as char(1)) returns @myvalues Table (id int identity(1,1),myval nvarchar(100))
as 
--Kamel Gazzah
--23/04/2019
begin
with cte as(
select @str [mystr],
cast(1 as int) [Start],
charindex(@separator,@str)as Nd
union all
select substring(@str,nd+1,len(@str)),cast(Nd+1 as int),charindex(@separator,@str,Nd+1) from cte
where nd>0
)
insert into @myvalues(myval) 
select case when nd>0 then substring(@str,start,Nd-start) 
else substring(@str,start,len(@str)) end [splitted] 
from cte   OPTION (MAXRECURSION 1000);
return ;
end;