SQL Table 值函数

SQL Table valued function

我有一个 Table 值函数如下。但它给出了一个错误。那就是说“消息 156,级别 15,状态 1,过程 GetOpeningByRepAcc,第 36 行 关键字 'begin'."

附近的语法不正确

但我没能解决这个问题。有什么想法吗?

create FUNCTION [dbo].[GetOpeningByRepAcc]
(
 @Date datetime,@AccId int,@CenterId datetime,@ItemId int
)
RETURNS @ReturnData TABLE
(
Opening decimal(10,3),
Topup decimal(10,3),
Returnsv decimal(10,3)
)
as
begin   
declare @opening decimal(10,3)
declare @topup decimal(10,3)
declare @returns decimal(10,3)

set @opening = (SELECT sum(OpeningQty)
FROM DailyItemStock
WHERE DistributionCenterId = @CenterId AND 
SalesRepAccId = @AccId AND ItemMasterId = @ItemId
and convert(varchar(10),StockDate,111) = convert(varchar(10),@Date,111))

set @topup = (SELECT     sum(Qty)
FROM         DailyItemStockTopUp
WHERE     
convert(varchar(10),TopupDate,111) = CONVERT(varchar(10), getdate(), 111)
AND DistributionCenterId = @CenterId AND SalesRepAccId = @AccId 
AND ItemMasterId =      @ItemId)

set @returns = (SELECT sum(TotReturns)
FROM DailyItemStock
WHERE DistributionCenterId = @CenterId AND 
SalesRepAccId = @AccId AND ItemMasterId = @ItemId
and convert(varchar(10),StockDate,111) = convert(varchar(10),@Date,111))
end

begin
insert @ReturnData
select @opening,@topup,@returns

return 
end

我想你多了一个end ... begin。请尝试以下版本的函数:

create FUNCTION [dbo].[GetOpeningByRepAcc]
(
 @Date datetime,@AccId int,@CenterId datetime,@ItemId int
)
RETURNS @ReturnData TABLE
(
Opening decimal(10,3),
Topup decimal(10,3),
Returnsv decimal(10,3)
)
as
begin   
    declare @opening decimal(10,3)
    declare @topup decimal(10,3)
    declare @returns decimal(10,3)

    set @opening = (SELECT sum(OpeningQty)
    FROM DailyItemStock
    WHERE DistributionCenterId = @CenterId AND 
    SalesRepAccId = @AccId AND ItemMasterId = @ItemId
    and convert(varchar(10),StockDate,111) = convert(varchar(10),@Date,111))

    set @topup = (SELECT     sum(Qty)
    FROM         DailyItemStockTopUp
    WHERE     
    convert(varchar(10),TopupDate,111) = CONVERT(varchar(10), getdate(), 111)
    AND DistributionCenterId = @CenterId AND SalesRepAccId = @AccId 
    AND ItemMasterId =      @ItemId)

    set @returns = (SELECT sum(TotReturns)
    FROM DailyItemStock
    WHERE DistributionCenterId = @CenterId AND 
    SalesRepAccId = @AccId AND ItemMasterId = @ItemId
    and convert(varchar(10),StockDate,111) = convert(varchar(10),@Date,111))

    insert into @ReturnData
    select @opening,@topup,@returns

    return 
end

BEGIN 和 END 未正确关闭:

CREATE FUNCTION [dbo].[Getopeningbyrepacc] (@Date     DATETIME,
                                            @AccId    INT,
                                            @CenterId DATETIME,
                                            @ItemId   INT)
RETURNS @ReturnData TABLE (
  Opening  DECIMAL(10, 3),
  Topup    DECIMAL(10, 3),
  Returnsv DECIMAL(10, 3))
AS
  BEGIN
      DECLARE @opening DECIMAL(10, 3)
      DECLARE @topup DECIMAL(10, 3)
      DECLARE @returns DECIMAL(10, 3)

      SET @opening = (SELECT Sum(OpeningQty)
                      FROM   DailyItemStock
                      WHERE  DistributionCenterId = @CenterId
                             AND SalesRepAccId = @AccId
                             AND ItemMasterId = @ItemId
                             AND CONVERT(VARCHAR(10), StockDate, 111) = CONVERT(VARCHAR(10), @Date, 111))
      SET @topup = (SELECT Sum(Qty)
                    FROM   DailyItemStockTopUp
                    WHERE  CONVERT(VARCHAR(10), TopupDate, 111) = CONVERT(VARCHAR(10), Getdate(), 111)
                           AND DistributionCenterId = @CenterId
                           AND SalesRepAccId = @AccId
                           AND ItemMasterId = @ItemId)
      SET @returns = (SELECT Sum(TotReturns)
                      FROM   DailyItemStock
                      WHERE  DistributionCenterId = @CenterId
                             AND SalesRepAccId = @AccId
                             AND ItemMasterId = @ItemId
                             AND CONVERT(VARCHAR(10), StockDate, 111) = CONVERT(VARCHAR(10), @Date, 111))

      BEGIN
          INSERT @ReturnData
          SELECT @opening,
                 @topup,
                 @returns

          RETURN
      END
  END 

您的函数中有两批 BEGIN... END 这是导致错误的原因。查看您的函数,尽管它可以大大简化,但您执行了几乎相同的查询 3 次,只是对不同的列求和,其中两个是:

SET @Topup = (  SELECT  SUM(Qty)
                FROM    DailyItemStock
                WHERE   DistributionCenterId = @CenterId 
                AND     SalesRepAccId = @AccId 
                AND     ItemMasterId = @ItemId
                AND     CONVERT(VARCHAR(10),TopupDate,111) = CONVERT(VARCHAR(10), GETDATE(), 111)
            );

SET @returns = (SELECT  SUM(TotReturns)
                FROM    DailyItemStock
                WHERE   DistributionCenterId = @CenterId 
                AND     SalesRepAccId = @AccId 
                AND     ItemMasterId = @ItemId
                AND     CONVERT(VARCHAR(10),TopupDate,111) = CONVERT(VARCHAR(10), GETDATE(), 111)
            );

您可以在一条语句中完成此操作:

SELECT  @Topup = SUM(Qty),
        @returns = SUM(TotReturns)
FROM    DailyItemStock
WHERE   DistributionCenterId = @CenterId 
AND     SalesRepAccId = @AccId 
AND     ItemMasterId = @ItemId
AND     CAST(StockDate AS DATE) = CAST(GETDATE() AS DATE);

n.b。我已经将你的谓词转换日期更改为 varchars 以比较它们(我假设删除时间)因为这是糟糕的做法,它执行得非常糟糕并且不能在日期列上使用任何索引

考虑到以上几点,我倾向于将其设为内联 TVF,它的性能会好得多:

CREATE FUNCTION [dbo].[GetOpeningByRepAcc]
(
    @Date       DATETIME,
    @AccId      INT,
    @CenterId   DATETIME,
    @ItemId     INT
)
RETURNS TABLE 
AS
RETURN
(   SELECT  Opening = SUM(OpeningQty),
            Topup = SUM(Qty),
            Returnsv = SUM(TotReturns)
    FROM    DailyItemStock
    WHERE   DistributionCenterId = @CenterId 
    AND     SalesRepAccId = @AccId 
    AND     ItemMasterId = @ItemId
    AND     CAST(StockDate AS DATE) = CAST(GETDATE() AS DATE)
);

内联 Table 值函数的好处是它们的行为更像视图,因为它们的定义可以扩展到外部查询并随后进行优化,并且不会像 RBAR 那样执行使用 BEGIN...END

的函数