如何将一组静态列列数据同时传递到存储过程中?

时间:2017-09-13 11:35:28

标签: sql-server stored-procedures

我的存储过程是

   ALTER PROCEDURE [dbo].[Register]
    @Id        int,
    @Name nvarchar(50)
AS
BEGIN
    BEGIN TRY
        INSERT INTO dbo.Group (Id, Name) 
        VALUES(@Id, @Name)

        SELECT 0
    END TRY
    BEGIN CATCH
        SELECT -1
    END CATCH
END
GO

我希望将此数据传递给此表

@Id = 1 
@Name = 'test1,test2,test3,test4,test5'

并且结果如此

Id   Name
1    test1
1    test2
1    test3
1    test4
1    test5

请分享实现这一目标的最佳方式。

3 个答案:

答案 0 :(得分:2)

SQL Server 2016提供了string_split(),它完全符合您的要求:

ALTER PROCEDURE [dbo].[Register] (
    @Id   int,
    @Name nvarchar(max)
) AS
BEGIN
    BEGIN TRY
        WITH s AS (
            SELECT STRING
        INSERT INTO dbo.Group (Id, Name) 
            VALUES(@Id, @Name)
            SELECT i.id, s.val
            FROM (SELECT @id as id) s CROSS APPLY
                 STRING_SPLIT(name, ',') s(val)

        SELECT 0
    END TRY
    BEGIN CATCH
        SELECT -1
    END CATCH
END;
GO

对于早期版本的SQL Server,您可以在网上找到string_split()的代码。

答案 1 :(得分:2)

您可以使用TVP:

  1. 创建用户定义的表类型

    CREATE TYPE [dbo].[TestTableType] AS TABLE(
                                                Id [int] NOT NULL,
                                                Name varchar(10)
                                              )
    
  2. 将其作为参数传递给存储过程

    ALTER PROCEDURE [dbo].[Register]
        @testTable TestTableType READONLY
    AS
    BEGIN
    BEGIN TRY
        INSERT INTO dbo.Group (Id, Name) 
        SELECT *
        FROM @testTable
    
        SELECT 0
    END TRY
    BEGIN CATCH
        SELECT -1
    END CATCH
    END
    
  3. 您可以在documentation中找到更多信息,请注意,当用作存储过程参数时,TVP必须声明为READONLY

答案 2 :(得分:0)

首先创建一个split函数,如下所示:

create FUNCTION [dbo].[fnSplit](
    @sInputList VARCHAR(max) -- List of delimited items
  , @sDelimiter VARCHAR(5) -- delimiter that separates items
) RETURNS @List TABLE (item VARCHAR(max))

BEGIN
DECLARE @sItem VARCHAR(max)
WHILE CHARINDEX(@sDelimiter,@sInputList,0) <> 0
 BEGIN
 SELECT
  @sItem=RTRIM(LTRIM(SUBSTRING(@sInputList,1,CHARINDEX(@sDelimiter,@sInputList,0)-1))),
  @sInputList=RTRIM(LTRIM(SUBSTRING(@sInputList,CHARINDEX(@sDelimiter,@sInputList,0)+LEN(@sDelimiter),LEN(@sInputList))))

 IF LEN(@sItem) > 0
  INSERT INTO @List SELECT @sItem
 END

IF LEN(@sInputList) > 0
 INSERT INTO @List SELECT @sInputList -- Put the last item in
RETURN
END

然后,您将能够按照这些方式做点什么:

declare @test table
(
id int,
name varchar(20)
)

declare @list varchar(MAX) = 'test1,test2,test3,test4,test5'
declare @id int = 1

INSERT INTO @test SELECT @id, * from dbo.fnSplit(@list,',')

SELECT * FROM @test

返回

1   test1
1   test2
1   test3
1   test4
1   test5

显然你不需要选择,但我只想证明插入工作正常!