sql >> Databasteknik >  >> RDS >> Sqlserver

SQL-funktionsproblem Den sista satsen som ingår i en funktion måste vara en retursats

Som felet antyder måste den sista satsen vara en retursats. Till skillnad från vissa andra språk flödet av IF/ELSE satsen kontrolleras inte under kompileringen, så SQL Server är inte medveten om att en av grenarna är obligatoriska (även ELSE ). Eftersom detta inte är markerat finns det inget sätt att veta om funktionen kommer att returnera ett värde om inte den sista satsen är en retursats. Även en enkel funktion som denna kommer att misslyckas:

CREATE FUNCTION dbo.FlowTest()
RETURNS INT
AS
BEGIN
    IF 1 = 1
    BEGIN
        RETURN 1;
    END
    ELSE
    BEGIN
        RETURN 0;
    END
END

Lösningen är att bara ta bort ELSE :

CREATE FUNCTION dbo.FlowTest()
RETURNS INT
AS
BEGIN
    IF 1 = 1
    BEGIN
        RETURN 1;
    END
    -- ELSE REMOVED
    RETURN 0;

END

Funktionen kommer att stoppa exekveringen när den når den första RETURN , alltså ELSE krävs ändå inte.

Så din funktion skulle bli:

ALTER FUNCTION [dbo].[GetBatchReleaseQuantity]   
(
@i_LocationID VARCHAR(50),
    @i_ProductID INT,
    @i_StartDate VARCHAR(50),  
    @i_EndDate VARCHAR(50),  
    @i_ProductInFlow int
)  
RETURNS numeric(18,3)  
 --WITH ENCRYPTION     
AS  
BEGIN  

  IF (@i_ProductInFlow ='2')
  BEGIN

    RETURN (SElECT  ISNULL( SUM( BatchReleaseQuantity),0.00)  
            FROM    BatchReleaseDetails BRD
                    LEFT OUTER JOIN BatchRelease BR 
                        ON BR.BatchReleaseID=BRD.BatchReleaseID
            WHERE   ProductId = @i_ProductID  
            AND     LocationID = @i_LocationID 
            AND     BRD.CreatedOn >= CONVERT(DATETIME, @i_StartDate+' 00:00:00') 
            AND     BRD.CreatedOn <= CONVERT(DATETIME,@i_EndDate + ' 23:59:59')
        )
  END

  RETURN (  SELECT  ISNULL( SUM( AcceptedQuantity),0.00)  
            FROM    GoodsReceivedNoteDetail GRND
                    LEFT OUTER JOIN GoodsReceivedNote GRN 
                        ON [email protected]_LocationID
            WHERE   ProductId = @i_ProductID  
            AND     GRN.LocationID = @i_LocationID 
            AND     GRND.CreatedOn >= CONVERT(DATETIME, @i_StartDate+' 00:00:00') 
            AND     GRND.CreatedOn <= CONVERT(DATETIME, @i_EndDate+' 23:59:59')
        )
  END 

END

Jag kan dock inte se hur funktionen kommer att fungera bra, och varför du passerar ett datum som en varchar är förståndig. Bryr du dig inte om saker som skapades mellan 23:59:59 och midnatt?

Jag skulle vara benägen att omfaktorera detta som en inline-tabellvärderad funktion och använda datum korrekt, t.ex.

CREATE FUNCTION [dbo].[GetBatchReleaseQuantityTVP]   
(
    @i_LocationID VARCHAR(50),
    @i_ProductID INT,
    @i_StartDate DATE,  
    @i_EndDate DATE,  
    @i_ProductInFlow int
)  
RETURNS TABLE
 --WITH ENCRYPTION     
AS  
RETURN 
(   SElECT  ReturnValue = ISNULL( SUM( BatchReleaseQuantity),0.00)  
    FROM    BatchReleaseDetails BRD
            LEFT OUTER JOIN BatchRelease BR 
                ON BR.BatchReleaseID=BRD.BatchReleaseID
    WHERE   ProductId = @i_ProductID  
    AND     LocationID = @i_LocationID 
    AND     BRD.CreatedOn >= @i_StartDate
    AND     BRD.CreatedOn < DATEADD(DAY, 1, @i_EndDate)
    AND     @i_ProductInFlow ='2'
    UNION ALL
    SELECT  ISNULL(SUM( AcceptedQuantity),0.00)  
    FROM    GoodsReceivedNoteDetail GRND
            LEFT OUTER JOIN GoodsReceivedNote GRN 
                ON [email protected]_LocationID
    WHERE   ProductId = @i_ProductID  
    AND     GRN.LocationID = @i_LocationID 
    AND     GRND.CreatedOn >= @i_StartDate
    AND     GRND.CreatedOn < DATEADD(DAY, 1, @i_EndDate)
    AND     ISNULL(@i_ProductInFlow, '') != '2'
);

Sedan närhelst du skulle ringa dbo.GetBatchReleaseQuantity(...) ring helt enkelt (SELECT ReturnValue FROM dbo.GetBatchReleaseQuantityTVP(...)) . Detta kommer att prestera betydligt bättre och kommer också att undvika att personer skickar ogiltiga datum till en varchar-parameter.



  1. Skriver MySQL över en kolumn med samma värde vid uppdatering?

  2. Trunkera med skick

  3. Array i SQL Query?

  4. Oracle Välj Where Date Between Today