对表的每一行调用函数而不交叉应用

时间:2015-11-18 11:48:07

标签: tsql

我有这个tsql函数,它插入一个表变量:

create function fnListInfo(@id int) returns @res table(
 [itemId] INT,
 [name] NVARCHAR(255),
 [type] NVARCHAR(20),
 [unit] INT,
 [order] INT
)
BEGIN
INSERT INTO @res

SELECT category.stockcat_id, category.stockcat_name, category.type, NULL /*unit*/, category.order
FROM tblStock stock
JOIN dbo.Map category on stock.id = category.itemId
WHERE stock.id = @id

insert into @res
    SELECT t.*
    FROM @res r
    CROSS APPLY dbo.anotherFunction(r.itemId) AS t
    WHERE r.type = 'parent'

RETURN
END
GO

在fnListInfo的末尾,我想在res表中添加更多行。如果@res中的行是' parent',我想调用另一个函数(让它调用另一个函数),它具有与此函数相同的返回类型,并且其输入参数为int (来自fnListInfo的itemId),然后我想将另一个函数的结果添加到fnListInfo中的@res。

所以基本上我想为@res中的每一行调用anotherFunction,类型为' parent'并将结果附加到已存在的@res。

我试过这样做:

insert into @res
        SELECT t.*
        FROM @res r
        CROSS APPLY dbo.anotherFunction(r.itemId) AS t
        WHERE r.type = 'parent'

它有效。问题是它效率低下。还有更好的方法吗?

我不喜欢使用游标。

1 个答案:

答案 0 :(得分:0)

尝试将您的功能更改为inline table valued function

CREATE FUNCTION dbo.fnListInfo(@id int) 
RETURNS TABLE
AS
RETURN (
   SELECT t.*
   FROM (
        SELECT category.stockcat_id AS ItemId, category.stockcat_name AS name,
               category.type AS [type], NULL AS [unit] , category.[order] AS [order]
        FROM tblStock stock
        JOIN dbo.Map category 
          ON stock.id = category.itemId
        WHERE stock.id = @id) AS r
   CROSS APPLY dbo.anotherFunction(r.itemId) AS t
   WHERE r.type = 'parent'
   UNION ALL 
   SELECT category.stockcat_id AS ItemId, category.stockcat_name AS name,
          category.type AS [type], NULL AS [unit] , category.[order] AS [order]
   FROM tblStock stock
   JOIN dbo.Map category 
     ON stock.id = category.itemId
   WHERE stock.id = @id
);

如果可能,您应该将dbo.anotherFunction更改为内联表值函数。

我建议您阅读 Inline vs Multistatement Table Function