INSERT using T-SQL with 2 table-value functions

INSERT using T-SQL with 2 table-value functions

我有一个存储过程,它接受两个 NVARCHAR 参数,这些参数接受逗号分隔的名称和索引值列表,并将它们插入到 SQL 服务器数据库 table 中去吧。

CREATE PROCEDURE [dbo].[SplitAndSave]   
    @name nvarchar(MAX),
    @vals nvarchar(MAX)

数据的格式为每个@name id 与@vals 的匹配顺序相同:

@name = 1,2,3,4
@vals = 9,8,7,6

我找到了一个将一列拆分为 table 的函数,该函数独立运行良好,并将数据拆分为所需的行:

CREATE FUNCTION [dbo].[fnSplitString] ( 
    @string NVARCHAR(MAX), 
    @delimiter CHAR(1) 
) 
RETURNS @output TABLE(splitdata NVARCHAR(MAX) 
) 
BEGIN 

DECLARE @start INT, @end INT 
SELECT @start = 1, @end = CHARINDEX(@delimiter, @string) 

WHILE @start < LEN(@string) + 1 BEGIN 
    IF @end = 0  
        SET @end = LEN(@string) + 1

    INSERT INTO @output (splitdata)  
    VALUES(SUBSTRING(@string, @start, @end - @start)) 
    SET @start = @end + 1 
    SET @end = CHARINDEX(@delimiter, @string, @start)

END 

RETURN 

END

在我的存储过程中,我正在尝试 'combine' 两个 table 函数:

INSERT INTO KEY_DATA (name, value)
(SELECT splitdata from fnSplitString(@name, ',')), (SELECT splitdata from fnSplitString(@value, ','))

但是我得到一个错误:

Msg 512, Level 16, State 1, Procedure dbo.SplitAndSave, Line 17 [Batch Start Line 2]
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.

我想我可能需要将第一个 table 包裹到第二个中,但我认为这无法做到 'all in one go'。

有什么想法可以实现吗?当前使用 SQL Server Management Studio v17.8

问题不在于函数,而在于您如何插入数据。以下代码:

INSERT INTO KEY_DATA (name, value)
(SELECT splitdata from fnSplitString(@name, ',')), (SELECT splitdata from fnSplitString(@value, ','))

除了:

INSERT INTO KEY_DATA (name, value)
(one value of name), (one value of value)

但在您的语句中返回的值不止一个。就是这个问题。

您需要在您的函数中添加顺序索引并通过它加入函数。像这样:

INSERT INTO KEY_DATA (name, value)
SELECT DS1.splitdata 
      ,DS2.splitdata
from fnSplitString(@name, ',') DS1
INNER JOIN fnSplitString(@value, ',') DS2
    ON DS1.[OrderIndex] = DS2.[OrderINdex];

例如:

CREATE OR ALTER FUNCTION [dbo].[fnSplitString] 
( 
    @string NVARCHAR(MAX), 
    @delimiter CHAR(1) 
) 
RETURNS @output TABLE
(
    [orderID] BIGINT
   ,[splitdata] NVARCHAR(MAX)
) 
BEGIN 

    DECLARE @XML XML = CAST(N'<r><![CDATA[' + REPLACE(@string, @delimiter, ']]></r><r><![CDATA[') + ']]></r>' AS XML)

    INSERT INTO @output ([orderID], splitdata)
    SELECT  ROW_NUMBER() OVER(ORDER BY T.c)
           ,RTRIM(LTRIM(T.c.value('.', 'nvarchar(MAX)')))
    FROM @XML.nodes('//r') T(c)

    RETURN 

END 
GO


DECLARE @name NVARCHAR(MAX) = '1,2,3,4'
       ,@vals NVARCHAR(MAX) = '9,8,7,6'


SELECT DS1.[splitdata] 
      ,DS2.[splitdata]
from dbo.fnSplitString(@name, ',') DS1
INNER JOIN dbo.fnSplitString(@vals, ',') DS2
    ON DS1.[orderID] = DS2.[orderID];