SQL内联或标量函数?

时间:2009-10-15 16:12:28

标签: sql sql-server performance function

所以我需要一个将一堆行值连接成一个varchar的SQL函数。

我已经编写了函数但是现在我专注于什么是更好的性能选择。

标量函数是

CREATE FUNCTION fn_GetPatients_ByRecipient (@recipient int)
RETURNS varchar(max) 
AS
BEGIN
DECLARE @patients varchar(max)
SET @patients = ''
SELECT @patients = @patients + convert(varchar, Patient) + ';' FROM RecipientsPatients WHERE Recipient = @recipient
RETURN @patients
END

内联函数只返回一个包含所有值的表,而不是连接它们。

CREATE FUNCTION fn_GetPatients_ByRecipient (@recipient int)
RETURNS TABLE 
AS
RETURN
(
    SELECT Patient FROM RecipientsPatients WHERE Recipient = @recipient
)

然后我将这个表放在一个单独的函数中并将它们连接在一起。我认为第二种选择是最好的,因为我将逐行通过一个较小的数据集。任何关于我正确/错误的意见都将不胜感激。

由于

3 个答案:

答案 0 :(得分:2)

SQL Server中的字符串连接问题有几个解决方案,在Concatenating Row Values in Transact-SQL和网络上的其他类似文章中讨论了优缺点。

我最喜欢的解决方案是使用FOR XML PATH('')技巧。您使用的链分配方法工作正常,虽然没有官方支持,因此将来可能会中断。只要表值函数不执行完整扫描,即你的方法应该是最快的,如果不是 ,那么。您的Recipient索引涵盖Patient(使用include)。

我唯一要补充的是声明两个函数WITH SCHEMABINDING,这会产生改善性能的副作用。

答案 1 :(得分:1)

请参阅此处了解使用FOR XML PATH技巧的示例

set nocount on;
declare @t table (id int, name varchar(20), x char(1))
insert into @t (id, name, x)
select 1,'test1', 'a' union
select 1,'test1', 'b' union
select 1,'test1', 'c' union
select 2,'test2', 'a' union
select 2,'test2', 'c' union
select 3,'test3', 'b' union
select 3,'test3', 'c' 


SELECT p1.id, p1.name,
          stuff((SELECT ', ' + x
              FROM @t p2
             WHERE p2.id  = p1.id
             ORDER BY name, x
               FOR XML PATH('') ), 1,2, '') AS p3
      FROM @t p1
     GROUP BY 
        id, name

它返回

1   test1   a, b, c
2   test2   a, c
3   test3   b, c

答案 2 :(得分:0)

看看Adam Machanic的Grouped String Concatenation Contest的结果:

http://web.archive.org/web/20150328021904/http://sqlblog.com/blogs/adam_machanic/archive/2009/05/31/grouped-string-concatenation-the-winner-is.aspx

它有代码向您展示最有效的方法。赢得比赛的Peter Larsson使用了包括XML PATH在内的各种技巧来完成任务。后来有一些争论是否是基于其他提交的后续测试的最有效的解决方案。确保检查注释以了解可以在那里下载的zip文件中查看哪些脚本。通常,FOR XML PATH('')是最快的。