问题描述
我想将名称列表传递给存储过程,然后执行左联接。我已经将名称列表作为表值参数传递了。
CREATE PROCEDURE [DBO].[INSERTANDGETLATESTNAMES]
(@list [dbo].[NamesCollection] READONLY)
AS
BEGIN
INSERT INTO [dbo].[Employee](NAME)
OUTPUT INSERTED.NAME
SELECT NamesCollection.Name
FROM @list AS NamesCollection
LEFT JOIN [dbo].[Employee] AS emp ON NamesCollection.Name = emp.Name
WHERE emp.Name IS NULL
END
用户定义的表格类型:
CREATE TYPE [dbo].[NamesCollection] AS TABLE
(
[NAME] [varchar](50) NULL
)
GO
在上述情况下,sql Server不会维护有关表值参数的统计信息,这将影响连接性能。如果性能较慢,那么我可以通过逗号分隔的字符串传递名称列表并编写一个函数来拆分表并将表返回到存储过程吗?
CREATE FUNCTION split_string_XML
(@in_string VARCHAR(MAX),@delimiter VARCHAR(1))
RETURNS @list TABLE(NAMES VARCHAR(50))
AS
BEGIN
DECLARE @sql_xml XML = Cast('<root><U>'+ Replace(@in_string,@delimiter,'</U><U>')+ '</U></root>' AS XML)
INSERT INTO @list(NAMES)
SELECT f.x.value('.','VARCHAR(50)') AS NAMES
FROM @sql_xml.nodes('/root/U') f(x)
WHERE f.x.value('.','VARCHAR(50)') <> ''
RETURN
END
GO
或
CREATE FUNCTION split_string_delimiter
(@in_string VARCHAR(MAX),@delimiter VARCHAR(1))
RETURNS @list TABLE(NAME VARCHAR(50))
AS
BEGIN
INSERT INTO @list(NAME)
SELECT value AS NAMES
FROM STRING_SPLIT(@in_string,@delimiter);
RETURN
END
GO
解决方法
使用STRING_SPLIT
优于使用XML PATH
进行拆分。如果可以使用STRING_SPLIT
,则可以使用JSON PATH
。
使用JSON PATH
,将JSON variable
转换为行集,然后将其插入#temporary table
,而不是@table variable
,这取决于您的SQL Server版本,#temporary tables
的表现更好处理大量数据时。
此外,如果您想向JSON variable
添加新字段,则无需编辑table type
。由于引用,在编辑table type
时很困难。
使用表值参数的SELECT非常简单。 这只是一个联接,假设表变量的基数计算为一个,并假设dbo.Employee.Name已建立索引并且列类型匹配,则该联接将使用循环联接来实现,而循环联接是最快的选择情况。
只需确保正确索引了dbo.Employee.Name。