将标量值函数转换为表值函数

时间:2017-11-04 13:55:45

标签: sql sql-server sql-server-2014

我有一个标量函数,用于计算客户帐户的运行余额,如下所示:

CREATE FUNCTION [dbo].[UDF_GetBalance] (@CustRef bigint, @ID bigint)
RETURNS decimal(18,2)
AS
BEGIN
  DECLARE @Balance decimal(18,2)
  SELECT @Balance = SUM(DebitAmount - CreditAmount) OVER (PARTITION BY CustReference ORDER BY Id 
                                      ROWS UNBOUNDED PRECEDING) 
FROM
CustomerLedgerEntries WHERE CustReference =@CustRef and ID <= @id

RETURN @Balance
END

要将此功能添加到表中,我运行此查询:

ALTER TABLE CustomerLedgerEntries ADD Balance as (dbo.UDF_GetBalance(CustReference, ID))

现在我在表格中添加了一个Balance列,显示每个客户的运行余额,使用DebitAmount和CreditAmount计算。

但是,随着数据库的增长,我注意到由于此功能而导致严重的性能问题。

问题:请您指点一下如何将其转换为表值函数并创建列余额并将TVF应用于它?我创建了这个TVF:

CREATE FUNCTION dbo.UDF_GetBalance2 (@CustRef bigint)
RETURNS TABLE AS RETURN
  SELECT balance = SUM(DebitAmount - CreditAmount) 
    OVER (PARTITION BY CustReference ORDER BY Id ROWS UNBOUNDED PRECEDING) 
FROM CustomerLedgerEntries 
WHERE CustReference =@CustRef;
GO

我想这应该可行,但我如何ALTER TABLE CustomerLedgerEntries ADD Balance as...使用TVF?

我需要按原样使用表,使用来自C#应用程序的预填充Balance值。提前谢谢。

3 个答案:

答案 0 :(得分:1)

AFAIK,你做不到,如果可以的话,我不会推荐它。这里适当的模式是创建一个视图,例如vw_CustomerLedgerEntries,具有Balance列,可以通过应用itv函数,也可以立即在视图中使用。然后,您将使用视图而不是表格。

答案 1 :(得分:1)

为什么要写一个表值函数?只需使用视图:

select cle.*,
       sum(DebitAmount - CreditAmount) over (partition by CustReference order by Id) as balance
from CustomerLedgerEntries;

答案 2 :(得分:0)

根据上面的回答,我创建了一个这样的视图:

CREATE VIEW [dbo].[V_CustomerLedgerEntry]
AS
Select * 
        , Sum(DebitAmount - CreditAmount) Over( Partition By CustReference Order by Id 
                                    rows Unbounded Preceding) As Balance 
 From CustomerLedgerEntries

我刚刚使用EF代码来根据此链接使用视图:USING SQL VIEWS WITH ENTITY FRAMEWORK CODE FIRST

谢谢大家的帮助。