【发布时间】:2020-02-10 05:18:04
【问题描述】:
我有一个存储过程,它接受两个 NVARCHAR 参数,这些参数接受以逗号分隔的名称和索引值列表,并将它们一次性插入到 SQL Server 数据库表中。
CREATE PROCEDURE [dbo].[SplitAndSave]
@name nvarchar(MAX),
@vals nvarchar(MAX)
数据将采用与@vals 相同的顺序匹配每个@name id 的格式:
@name = 1,2,3,4
@vals = 9,8,7,6
我找到了一个函数,它可以将一列拆分为一个独立工作的表,并将数据拆分为所需的行:
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
在我的存储过程中,我试图“组合”这两个表函数:
INSERT INTO KEY_DATA (name, value)
(SELECT splitdata from fnSplitString(@name, ',')), (SELECT splitdata from fnSplitString(@value, ','))
但我得到一个错误:
消息 512,级别 16,状态 1,过程 dbo.SplitAndSave,第 17 行 [批处理开始行 2]
子查询返回超过 1 个值。当子查询跟随 =、!=、、>= 或子查询用作表达式时,这是不允许的。
我想我可能需要将第一个表包装到第二个表中,但我认为这不能“一次性”完成。
有什么想法可以做到这一点吗?目前使用 SQL Server Management Studio v17.8
【问题讨论】:
-
检查 SQL Server 中的official MS Docs on functions,您会看到:限制和限制:用户定义的函数不能用于执行的操作修改数据库状态。您不能在函数中执行此操作 - 您需要改用存储过程
-
是的,知道我必须使用存储过程来完成这项任务。
-
如果可能的话,您应该避免在 SQL 中完全使用逗号分隔的字符串 - 您最好将单个表值参数传递到您的存储过程中。
标签: sql-server tsql stored-procedures table-valued-parameters