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];
我有一个存储过程,它接受两个 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];