调用行子集的函数

时间:2015-09-26 18:58:31

标签: sql sql-server sql-server-2012 udf

我在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

这是我数据的简化。

我有一个标量函数,它将这些数据作为用户定义的表类型(整个数据表),进行一些处理(非常复杂,许多规则),然后为每个id返回一个字符串,例如:对于id为1的数据子集,它将返回开放式厨房,对于id为2的数据子集,它将返回空调,宽敞的起居室,类似于id 3它将返回金属瓦屋顶。我的函数必须为每个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

这是我的表类型

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

1 个答案:

答案 0 :(得分:0)

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

<强> 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;

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