SQL表值函数

时间:2015-01-02 10:35:35

标签: sql sql-server sql-server-2008 sql-function

我有一个表值函数如下。但它给出了一个错误。这就是说" Msg 156,Level 15,State 1,Procedure GetOpeningByRepAcc,Line 36 关键字'开始'附近的语法不正确。"

但我无法解决这个问题。好吗?

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

3 个答案:

答案 0 :(得分:2)

你的函数中有两批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)
);

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

答案 1 :(得分:0)

我认为你还有一个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

答案 2 :(得分:0)

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 
相关问题