行子集的调用函数

Call function for subset of rows

我在 SQL Server 2012 数据库中有以下数据:

CategoryID  Keyword             Type
-------------------------------------
1           open plan           0
1           kitchen             0
2           air conditioned     3
2           spacious            2
2           living room         1 
3           metal               5
3           shingled            4
3           roof                4

这是我的数据的简化。

我有一个标量函数,它将此数据作为用户定义的 table 类型(整个 table 数据)进行处理(非常复杂,有很多规则)然后 returns 每个 id 的字符串,例如对于 ID 为 1 的数据子集,它将 return open plan kitchen,对于 ID 为 2 的数据子集,它将 return air空调宽敞的客厅,与 id 3 类似,它将 return 金属瓦屋顶 。我的函数必须为每个 id 执行此操作。目前,我正在使用游标循环遍历不同的 id,并为与 id 匹配的每组数据调用该函数。

我担心性能。执行此操作的更好方法是什么?

函数示例:

CREATE FUNCTION [dbo].[func_GenerateString]
(
    @MyData InputDataType READONLY
)
RETURNS VARCHAR(MAX)
AS
BEGIN
    DECLARE @outputString VARCHAR(MAX)
    SET @outputString = ''

    -- implement rules
    RETURN @outputString 
END

这是我的table类型

CREATE TYPE InputDataType AS TABLE 
(   
    CategoryId INT NOT NULL,
    Keyword varchar(100) NULL,
    Type INT NOT NULL,
)
GO

我认为您可以使用以下解决方法:

SqlFiddleDemo

CREATE TYPE InputDataType AS TABLE 
(   
    CategoryId INT NOT NULL,
    Keyword varchar(100) NULL,
    Type INT NOT NULL
);
GO

CREATE FUNCTION [dbo].[func_GenerateString]( @MyXml XML)
RETURNS VARCHAR(MAX)
AS
BEGIN

    /* Unwrapping */
    DECLARE @MyData AS InputDataType;

    INSERT INTO @MyData(CategoryId, Keyword, Type)
    SELECT 
        [CategoryId] = t.c.value('(CategoryId)[1]', 'int'),
        [Keyword]    = t.c.value('(Keyword)[1]', 'varchar(100)') ,
        [Type]       = t.c.value('(Type)[1]', 'int') 
    FROM @MyXml.nodes('//row') AS t(c);


    DECLARE @outputString VARCHAR(MAX);
    SET @outputString = '';

    -- your logic
    SET @outputString = STUFF(
                       (SELECT ' ' + Keyword
                        FROM @MyData
                        FOR XML PATH('')), 1, 1, '')

    RETURN @outputString 
END;
GO


 /* Main query */
SELECT CategoryId,
    [result] =  [dbo].[func_GenerateString]((SELECT CategoryId, Keyword, Type
                                             FROM tab t1
                                             WHERE t.CategoryId = t1.CategoryId 
                                             FOR XML PATH, ROOT('root')))
FROM tab t
GROUP BY CategoryId;

我传递 XML 参数而不是 TVP 参数,并立即在函数内部将其解包回 TVP。