69

使用 Like 和 In的
动态 SQL 逗号分隔值查询参数化查询的重复

我有一个 SQL Server 存储过程,我想将一个varchar完整的逗号分隔值传递给一个IN函数。例如:

DECLARE @Ids varchar(50);
SET @Ids = '1,2,3,5,4,6,7,98,234';

SELECT * 
FROM sometable 
WHERE tableid IN (@Ids);

这当然行不通。我得到错误:

将 varchar 值 '1,2,3,5,4,6,7,98,234' 转换为数据类型 int 时转换失败。

我怎样才能在不求助于构建动态 SQL 的情况下完成这个(或类似的事情)?

4

26 回答 26

62

当然,如果你像我一样懒惰,你可以这样做:

Declare @Ids varchar(50) Set @Ids = ',1,2,3,5,4,6,7,98,234,'

Select * from sometable
 where Charindex(','+cast(tableid as varchar(8000))+',', @Ids) > 0
于 2009-05-19T03:16:20.303 回答
45

不要使用循环分割字符串的函数!,我下面的函数将非常快地分割一个字符串,没有循环!

在你使用我的功能之前,你需要建立一个“帮助”表,每个数据库只需要这样做一次:

CREATE TABLE Numbers
(Number int  NOT NULL,
    CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (Number ASC)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
DECLARE @x int
SET @x=0
WHILE @x<8000
BEGIN
    SET @x=@x+1
    INSERT INTO Numbers VALUES (@x)
END

使用这个函数来分割你的字符串,它不会循环并且非常快:

CREATE FUNCTION [dbo].[FN_ListToTable]
(
     @SplitOn              char(1)              --REQUIRED, the character to split the @List string on
    ,@List                 varchar(8000)        --REQUIRED, the list to split apart
)
RETURNS
@ParsedList table
(
    ListValue varchar(500)
)
AS
BEGIN

/**
Takes the given @List string and splits it apart based on the given @SplitOn character.
A table is returned, one row per split item, with a column name "ListValue".
This function workes for fixed or variable lenght items.
Empty and null items will not be included in the results set.


Returns a table, one row per item in the list, with a column name "ListValue"

EXAMPLE:
----------
SELECT * FROM dbo.FN_ListToTable(',','1,12,123,1234,54321,6,A,*,|||,,,,B')

    returns:
        ListValue  
        -----------
        1
        12
        123
        1234
        54321
        6
        A
        *
        |||
        B

        (10 row(s) affected)

**/



----------------
--SINGLE QUERY-- --this will not return empty rows
----------------
INSERT INTO @ParsedList
        (ListValue)
    SELECT
        ListValue
        FROM (SELECT
                  LTRIM(RTRIM(SUBSTRING(List2, number+1, CHARINDEX(@SplitOn, List2, number+1)-number - 1))) AS ListValue
                  FROM (
                           SELECT @SplitOn + @List + @SplitOn AS List2
                       ) AS dt
                      INNER JOIN Numbers n ON n.Number < LEN(dt.List2)
                  WHERE SUBSTRING(List2, number, 1) = @SplitOn
             ) dt2
        WHERE ListValue IS NOT NULL AND ListValue!=''



RETURN

END --Function FN_ListToTable

您可以将此函数用作连接中的表:

SELECT
    Col1, COl2, Col3...
    FROM  YourTable
        INNER JOIN FN_ListToTable(',',@YourString) s ON  YourTable.ID = s.ListValue

这是您的示例:

Select * from sometable where tableid in(SELECT ListValue FROM dbo.FN_ListToTable(',',@Ids) s)
于 2009-05-18T17:49:11.430 回答
24

无表无功能无循环

基于将您的列表解析为我们的 DBA 建议使用 XML 的表的想法。

Declare @Ids varchar(50)
Set @Ids = ‘1,2,3,5,4,6,7,98,234’

DECLARE @XML XML
SET @XML = CAST('<i>' + REPLACE(@Ids, ',', '</i><i>') + '</i>' AS XML)

SELECT * 
FROM
    SomeTable 
    INNER JOIN @XML.nodes('i') x(i) 
        ON  SomeTable .Id = x.i.value('.', 'VARCHAR(MAX)')

这些似乎与@KM 的答案具有相同的性能,但我认为要简单得多。

于 2013-06-05T09:48:08.750 回答
11

您可以创建一个返回表的函数。

所以你的陈述会是这样的

select * from someable 
 join Splitfunction(@ids) as splits on sometable.id = splits.id

这是一个模拟函数。

CREATE FUNCTION [dbo].[FUNC_SplitOrderIDs]
(
    @OrderList varchar(500)
)
RETURNS 
@ParsedList table
(
    OrderID int
)
AS
BEGIN
    DECLARE @OrderID varchar(10), @Pos int

    SET @OrderList = LTRIM(RTRIM(@OrderList))+ ','
    SET @Pos = CHARINDEX(',', @OrderList, 1)

    IF REPLACE(@OrderList, ',', '') <> ''
    BEGIN
        WHILE @Pos > 0
        BEGIN
            SET @OrderID = LTRIM(RTRIM(LEFT(@OrderList, @Pos - 1)))
            IF @OrderID <> ''
            BEGIN
                INSERT INTO @ParsedList (OrderID) 
                VALUES (CAST(@OrderID AS int)) --Use Appropriate conversion
            END
            SET @OrderList = RIGHT(@OrderList, LEN(@OrderList) - @Pos)
            SET @Pos = CHARINDEX(',', @OrderList, 1)

        END
    END 
    RETURN
END
于 2009-05-18T17:29:30.800 回答
9

这是一个很常见的问题。罐头答案,几个不错的技巧:

http://www.sommarskog.se/arrays-in-sql-2005.html

于 2009-05-18T19:52:01.370 回答
8

这完美!下面的答案太复杂了。不要将其视为动态的。如下设置您的存储过程:

(@id as varchar(50))
as

Declare @query as nvarchar(max)
set @query ='
select * from table
where id in('+@id+')'
EXECUTE sp_executesql @query
于 2009-05-18T17:32:49.607 回答
6

在不使用动态 SQL 的情况下,您必须获取输入变量并使用拆分函数将数据放入临时表中,然后加入该表。

于 2009-05-18T17:26:13.817 回答
6

我可以建议WITH这样使用:

DECLARE @Delim char(1) = ',';
SET @Ids = @Ids + @Delim;

WITH CTE(i, ls, id) AS (
    SELECT 1, CHARINDEX(@Delim, @Ids, 1), SUBSTRING(@Ids, 1, CHARINDEX(@Delim, @Ids, 1) - 1)
    UNION ALL
    SELECT i + 1, CHARINDEX(@Delim, @Ids, ls + 1), SUBSTRING(@Ids, ls + 1, CHARINDEX(@Delim, @Ids, ls + 1) - CHARINDEX(@Delim, @Ids, ls) - 1)
    FROM CTE
    WHERE  CHARINDEX(@Delim, @Ids, ls + 1) > 1
)
SELECT t.*
FROM yourTable t
    INNER JOIN
    CTE c
    ON t.id = c.id;
于 2015-09-26T05:18:49.360 回答
6

我认为一个非常简单的解决方案可能如下:

DECLARE @Ids varchar(50);
SET @Ids = '1,2,3,5,4,6,7,98,234';

SELECT * 
FROM sometable 
WHERE ','+@Ids+',' LIKE '%,'+CONVERT(VARCHAR(50),tableid)+',%';
于 2017-05-31T06:07:43.087 回答
3

谢谢,我使用它的功能............这是我的示例

**UPDATE [RD].[PurchaseOrderHeader]
SET     [DispatchCycleNumber] ='10'
 WHERE  OrderNumber in(select * FROM XA.fn_SplitOrderIDs(@InvoiceNumberList))**


CREATE FUNCTION [XA].[fn_SplitOrderIDs]
(
    @OrderList varchar(500)
)
RETURNS 
@ParsedList table
(
    OrderID int
)
AS
BEGIN
    DECLARE @OrderID varchar(10), @Pos int

    SET @OrderList = LTRIM(RTRIM(@OrderList))+ ','
    SET @Pos = CHARINDEX(',', @OrderList, 1)

    IF REPLACE(@OrderList, ',', '') <> ''
    BEGIN
        WHILE @Pos > 0
        BEGIN
                SET @OrderID = LTRIM(RTRIM(LEFT(@OrderList, @Pos - 1)))
                IF @OrderID <> ''
                BEGIN
                        INSERT INTO @ParsedList (OrderID) 
                        VALUES (CAST(@OrderID AS int)) --Use Appropriate conversion
                END
                SET @OrderList = RIGHT(@OrderList, LEN(@OrderList) - @Pos)
                SET @Pos = CHARINDEX(',', @OrderList, 1)

        END
    END 
    RETURN
END
于 2010-03-05T06:37:15.320 回答
3

如果您使用 SQL Server 2008 或更高版本,请使用表值参数;例如:

CREATE PROCEDURE [dbo].[GetAccounts](@accountIds nvarchar)
AS
BEGIN
    SELECT * 
    FROM accountsTable 
    WHERE accountId IN (select * from @accountIds)
END

CREATE TYPE intListTableType AS TABLE (n int NOT NULL)

DECLARE @tvp intListTableType 

-- inserts each id to one row in the tvp table    
INSERT @tvp(n) VALUES (16509),(16685),(46173),(42925),(46167),(5511)

EXEC GetAccounts @tvp
于 2014-10-06T08:17:58.927 回答
3

已经有一段时间了,但我过去曾使用 XML 作为过渡。

我对此不以为然,但恐怕我不再知道我从哪里得到这个想法:

-- declare the variables needed
DECLARE @xml as xml,@str as varchar(100),@delimiter as varchar(10)

-- The string you want to split
SET @str='A,B,C,D,E,Bert,Ernie,1,2,3,4,5'

-- What you want to split on. Can be a single character or a string
SET @delimiter =','

-- Convert it to an XML document
SET @xml = cast(('<X>'+replace(@str,@delimiter ,'</X><X>')+'</X>') as xml)

-- Select back from the XML
SELECT N.value('.', 'varchar(10)') as value FROM @xml.nodes('X') as T(N)
于 2016-02-23T11:17:33.920 回答
3

创建一个像下面这样的表函数,它解析逗号分隔的 varchar 并返回一个可以与其他表进行内部连接的表。

CREATE FUNCTION [dbo].[fn_SplitList]
(
  @inString     varchar(MAX)  = '',
  @inDelimiter  char(1)       = ',' -- Keep the delimiter to 100 chars or less.  Generally a delimiter will be 1-2 chars only.
)
RETURNS @tbl_Return  table
(
  Unit  varchar(1000) COLLATE Latin1_General_BIN
)
AS
BEGIN 
    INSERT INTO @tbl_Return
    SELECT DISTINCT
      LTRIM(RTRIM(piece.value('./text()[1]', 'varchar(1000)'))) COLLATE DATABASE_DEFAULT AS Unit
    FROM
    (
      --
      --  Replace any delimiters in the string with the "X" tag.
      --
      SELECT
        CAST(('<X>' + REPLACE(s0.prsString, s0.prsSplitDelimit, '</X><X>') + '</X>') AS xml).query('.') AS units
      FROM
      (
        --
        --  Convert the string and delimiter into XML.
        --
        SELECT
          (SELECT @inString FOR XML PATH('')) AS prsString,
          (SELECT @inDelimiter FOR XML PATH('')) AS prsSplitDelimit
      ) AS s0
    ) AS s1
    CROSS APPLY units.nodes('X') x(piece)
  RETURN
END

================================================== 现在在您的代码中使用上面创建的表函数,函数的创建是您数据库中的一次性活动,可以跨数据库使用,也可以在同一台服务器上使用。

DECLARE @Ids varchar(50);
SET @Ids = '1,2,3,5,4,6,7,98,234';

SELECT
     *
FROM sometable AS st
INNER JOIN fn_SplitList(@ids, ',') AS sl
     ON sl.unit = st.tableid
于 2017-03-07T11:26:18.143 回答
2

我之前写过一个存储过程来展示如何做到这一点。您基本上必须处理字符串。我试图在这里发布代码,但格式变得很糟糕。

IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id(N'[dbo].[uspSplitTextList]') AND OBJECTPROPERTY(id, N'IsProcedure') = 1)
   DROP PROCEDURE [dbo].[uspSplitTextList]
GO

SET QUOTED_IDENTIFIER ON 
GO
SET ANSI_NULLS ON 
GO


/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
-- uspSplitTextList
--
-- Description:
--    splits a separated list of text items and returns the text items
--
-- Arguments:
--    @list_text        - list of text items
--    @Delimiter        - delimiter
--
-- Notes:
-- 02/22/2006 - WSR : use DATALENGTH instead of LEN throughout because LEN doesn't count trailing blanks
--
-- History:
-- 02/22/2006 - WSR : revised algorithm to account for items crossing 8000 character boundary
-- 09/18/2006 - WSR : added to this project
--
CREATE PROCEDURE uspSplitTextList
   @list_text           text,
   @Delimiter           varchar(3)
AS

SET NOCOUNT ON

DECLARE @InputLen       integer         -- input text length
DECLARE @TextPos        integer         -- current position within input text
DECLARE @Chunk          varchar(8000)   -- chunk within input text
DECLARE @ChunkPos       integer         -- current position within chunk
DECLARE @DelimPos       integer         -- position of delimiter
DECLARE @ChunkLen       integer         -- chunk length
DECLARE @DelimLen       integer         -- delimiter length
DECLARE @ItemBegPos     integer         -- item starting position in text
DECLARE @ItemOrder      integer         -- item order in list
DECLARE @DelimChar      varchar(1)      -- first character of delimiter (simple delimiter)

-- create table to hold list items
-- actually their positions because we may want to scrub this list eliminating bad entries before substring is applied
CREATE TABLE #list_items ( item_order integer, item_begpos integer, item_endpos integer )

-- process list
IF @list_text IS NOT NULL
   BEGIN

   -- initialize
   SET @InputLen = DATALENGTH(@list_text)
   SET @TextPos = 1
   SET @DelimChar = SUBSTRING(@Delimiter, 1, 1)
   SET @DelimLen = DATALENGTH(@Delimiter)
   SET @ItemBegPos = 1
   SET @ItemOrder = 1
   SET @ChunkLen = 1

   -- cycle through input processing chunks
   WHILE @TextPos <= @InputLen AND @ChunkLen <> 0
      BEGIN

      -- get current chunk
      SET @Chunk = SUBSTRING(@list_text, @TextPos, 8000)

      -- setup initial variable values
      SET @ChunkPos = 1
      SET @ChunkLen = DATALENGTH(@Chunk)
      SET @DelimPos = CHARINDEX(@DelimChar, @Chunk, @ChunkPos)

      -- loop over the chunk, until the last delimiter
      WHILE @ChunkPos <= @ChunkLen AND @DelimPos <> 0
         BEGIN

         -- see if this is a full delimiter
         IF SUBSTRING(@list_text, (@TextPos + @DelimPos - 1), @DelimLen) = @Delimiter
            BEGIN

            -- insert position
            INSERT INTO #list_items (item_order, item_begpos, item_endpos)
            VALUES (@ItemOrder, @ItemBegPos, (@TextPos + @DelimPos - 1) - 1)

            -- adjust positions
            SET @ItemOrder = @ItemOrder + 1
            SET @ItemBegPos = (@TextPos + @DelimPos - 1) + @DelimLen
            SET @ChunkPos = @DelimPos + @DelimLen

            END
         ELSE
            BEGIN

            -- adjust positions
            SET @ChunkPos = @DelimPos + 1

            END

         -- find next delimiter      
         SET @DelimPos = CHARINDEX(@DelimChar, @Chunk, @ChunkPos)

         END

      -- adjust positions
      SET @TextPos = @TextPos + @ChunkLen

      END

   -- handle last item
   IF @ItemBegPos <= @InputLen
      BEGIN

      -- insert position
      INSERT INTO #list_items (item_order, item_begpos, item_endpos)
      VALUES (@ItemOrder, @ItemBegPos, @InputLen)

      END

   -- delete the bad items
   DELETE FROM #list_items
   WHERE item_endpos < item_begpos

   -- return list items
   SELECT SUBSTRING(@list_text, item_begpos, (item_endpos - item_begpos + 1)) AS item_text, item_order, item_begpos, item_endpos
   FROM #list_items
   ORDER BY item_order

   END

DROP TABLE #list_items

RETURN

/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */

GO
SET QUOTED_IDENTIFIER OFF 
GO
SET ANSI_NULLS ON 
GO
于 2009-05-18T17:29:35.260 回答
2

我对用户 KM 有同样的想法。但不需要额外的表号。仅此功能。

CREATE FUNCTION [dbo].[FN_ListToTable]
(
    @SplitOn              char(1)              --REQUIRED, the character to split the @List string on
   ,@List                 varchar(8000)        --REQUIRED, the list to split apart
)
RETURNS
@ParsedList table
(
    ListValue varchar(500)
)
AS
BEGIN
    DECLARE @number int = 0
    DECLARE @childString varchar(502) = ''
    DECLARE @lengthChildString int = 0
    DECLARE @processString varchar(502) = @SplitOn + @List + @SplitOn

    WHILE @number < LEN(@processString)
    BEGIN
        SET @number = @number + 1
        SET @lengthChildString = CHARINDEX(@SplitOn, @processString, @number + 1) - @number - 1
        IF @lengthChildString > 0
        BEGIN
            SET @childString = LTRIM(RTRIM(SUBSTRING(@processString, @number + 1, @lengthChildString)))

            IF @childString IS NOT NULL AND @childString != ''
            BEGIN
                INSERT INTO @ParsedList(ListValue) VALUES (@childString)
                SET @number = @number + @lengthChildString - 1
            END
        END
    END

RETURN

END

这是测试:

SELECT ListValue FROM dbo.FN_ListToTable('/','a/////bb/c')

结果:

   ListValue
______________________
   a
   bb
   c
于 2016-11-29T02:14:38.913 回答
1
-- select * from dbo.Split_ID('77,106')  

    ALTER FUNCTION dbo.Split_ID(@String varchar(8000))     
    returns @temptable TABLE (ID varchar(8000))     
    as     
    begin     
        declare @idx int     
        declare @slice varchar(8000)     
        declare @Delimiter char(1)
         set @Delimiter =','

        select @idx = 1     
            if len(@String)<1 or @String is null  return     

        while @idx!= 0     
        begin     
            set @idx = charindex(@Delimiter,@String)     
            if @idx!=0     
                set @slice = left(@String,@idx - 1)     
            else     
                set @slice = @String     

            if(len(@slice)>0)
                insert into @temptable(ID) values(@slice)     

            set @String = right(@String,len(@String) - @idx)     
            if len(@String) = 0 break     
        end 
    return     
    end
于 2012-07-31T11:20:14.517 回答
1

你可以这样做:

create or replace 
PROCEDURE UDP_SETBOOKMARK 
(
  P_USERID IN VARCHAR2  
, P_BOOKMARK IN VARCHAR2  
) AS 
BEGIN

UPDATE T_ER_Bewertung
SET LESEZEICHEN = P_BOOKMARK
WHERE STAMM_ID in( select regexp_substr(P_USERID,'[^,]+', 1, level) from dual
                   connect by regexp_substr(P_USERID, '[^,]+', 1, level) is not null )
and ER_ID = (select max(ER_ID) from T_ER_Bewertung_Kopie);

commit;

END UDP_SETBOOKMARK;

然后尝试使用

Begin
UDP_SETBOOKMARK ('1,2,3,4,5', 'Test');
End;

您也可以在其他情况下将此 IN-Clause 与 regexp_substr 一起使用,只需尝试一下。

于 2014-12-22T12:58:08.593 回答
1
Error 493: The column 'i' that was returned from the nodes() method cannot be 
   used directly. It can only be used with one of the four XML data type 
   methods, exist(), nodes(), query(), and value(), or in IS NULL and IS NOT 
   NULL checks.

使用以下代码段在 SQL Server 2014 中修复了上述错误

Declare @Ids varchar(50)
Set @Ids = '1,2,3,5,4,6,7,98,234'

DECLARE @XML XML
SET @XML = CAST('<i>' + REPLACE(@Ids, ',', '</i><i>') + '</i>' AS XML)

SELECT SomeTable.* 
FROM
    SomeTable 
    cross apply @XML.nodes('i') x(i) 
        where SomeTable .Id = x.i.value('.', 'VARCHAR(MAX)')
于 2017-07-21T17:51:08.883 回答
1

试试这个:

SELECT ProductId, Name, Tags  
FROM Product  
WHERE '1,2,3,' LIKE '%' + CAST(ProductId AS VARCHAR(20)) + ',%'; 

该链接的最后一个示例所述

于 2017-08-20T03:31:36.447 回答
0

最好和简单的方法。

DECLARE @AccumulateKeywordCopy NVARCHAR(2000),@IDDupCopy NVARCHAR(50);
SET @AccumulateKeywordCopy ='';
SET @IDDupCopy ='';
SET @IDDup = (SELECT CONVERT(VARCHAR(MAX), <columnName>) FROM <tableName> WHERE <clause>)

SET @AccumulateKeywordCopy = ','+@AccumulateKeyword+',';
SET @IDDupCopy = ','+@IDDup +',';
SET @IDDupCheck = CHARINDEX(@IDDupCopy,@AccumulateKeywordCopy)
于 2014-11-06T10:36:53.643 回答
0
CREATE TABLE t 
  ( 
     id   INT, 
     col1 VARCHAR(50) 
  ) 

INSERT INTO t 
VALUES     (1, 
            'param1') 

INSERT INTO t 
VALUES     (2, 
            'param2') 

INSERT INTO t 
VALUES     (3, 
            'param3') 

INSERT INTO t 
VALUES     (4, 
            'param4') 

INSERT INTO t 
VALUES     (5, 
            'param5') 

DECLARE @params VARCHAR(100) 

SET @params = ',param1,param2,param3,' 

SELECT * 
FROM   t 
WHERE  Charindex(',' + Cast(col1 AS VARCHAR(8000)) + ',', @params) > 0 

工作小提琴在这里找到小提琴

于 2018-02-21T08:42:47.797 回答
0

我遇到了同样的问题,我不想在源数据库上留下任何足迹——即没有存储过程或函数。我是这样处理的:

declare @IDs table (Value int)

insert into @IDs values(1)
insert into @IDs values(2)
insert into @IDs values(3)
insert into @IDs values(5)
insert into @IDs values(4)
insert into @IDs values(6)
insert into @IDs values(7)
insert into @IDs values(98)
insert into @IDs values(234)


SELECT * 
FROM sometable 
WHERE tableid IN (select Value from @IDs)
于 2020-11-28T22:05:06.153 回答
0

@RBarryYoung(上图)的答案对我有用。但是当逗号分隔的字符串值之间有空格时,它将省略带空格的 ID。所以我删除了空格。

看看下面的代码片段。

Declare @Ids varchar(50) Set @Ids = '1   ,   2,3'
set @Ids=','+Replace(@Ids,' ', '')+',';

Select * from [tblEmployee]
where Charindex(','+cast(ID as varchar(8000))+',', @Ids) > 0
于 2021-05-11T12:16:01.720 回答
0

这里有很多答案,但要加上我的两分钱,我认为STRING_SPLIT这是解决此类问题的一种非常简单的方法:

DECLARE @Ids varchar(50);
SET @Ids = '1,2,3,5,4,6,7,98,234';

SELECT * 
FROM sometable 
WHERE tableid IN;
(SELECT value FROM STRING_SPLIT(@Ids, ','))
于 2021-06-10T04:22:41.123 回答
-1

我发现最简单的方法是使用 FIND_IN_SET

FIND_IN_SET(column_name, values)

values=(1,2,3)

SELECT name WHERE FIND_IN_SET(id, values)
于 2017-03-30T04:54:46.413 回答
-1

这对于我不想使用 CTE 也不想使用内部连接的要求之一非常有用。

DECLARE @Ids varchar(50);
SET @Ids = '1,2,3,5,4,6,7,98,234';
    
SELECT
   cn1,cn2,cn3
FROM tableName
WHERE columnName in (select Value from fn_SplitString(@ids, ','))

拆分字符串的功能:

CREATE FUNCTION [dbo].[fn_SplitString] ( @stringToSplit VARCHAR(MAX), @seperator Char )  
RETURNS  
 @returnList TABLE ([Value] [nvarchar] (500))  
AS  
BEGIN  
  
 DECLARE @name NVARCHAR(255)  
 DECLARE @pos INT  
  
 WHILE CHARINDEX(@seperator, @stringToSplit) > 0  
 BEGIN  
  SELECT @pos  = CHARINDEX(@seperator, @stringToSplit)    
  SELECT @name = SUBSTRING(@stringToSplit, 1, @pos-1)  
  
  INSERT INTO @returnList   
  SELECT @name  
  
  SELECT @stringToSplit = SUBSTRING(@stringToSplit, @pos+1, LEN(@stringToSplit)-@pos)  
 END  
  
 INSERT INTO @returnList  
 SELECT @stringToSplit  
  
 RETURN  
END  
于 2020-05-21T09:02:36.147 回答