sql >> Database teknologi >  >> RDS >> Sqlserver

SQL-funktionsproblem Den sidste sætning inkluderet i en funktion skal være en retursætning

Som fejlen antyder, skal den sidste erklæring være en returerklæring. I modsætning til nogle andre sprog strømmen af ​​IF/ELSE sætning er ikke kontrolleret under kompilering, så SQL Server er ikke klar over, at en af ​​grenene er obligatorisk (selv ELSE ). Da dette ikke er markeret, er der ingen måde at vide om funktionen vil returnere en værdi, medmindre den sidste sætning er en retursætning. Selv en simpel funktion som denne vil fejle:

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

Løsningen er bare at fjerne ELSE :

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

END

Funktionen stopper udførelsen, når den når den første RETURN , så ELSE er ikke påkrævet alligevel.

Så din funktion ville blive:

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

Jeg kan dog ikke se, hvordan funktionen vil fungere godt, og hvorfor du passerer en date som varchar er uden for mig. Er du ligeglad med ting, der blev skabt mellem 23:59:59 og midnat?

Jeg ville være tilbøjelig til at omfaktorere dette som en inline-tabelvurderet funktion og bruge datoer korrekt, f.eks.

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'
);

Så hver gang du ville kalde dbo.GetBatchReleaseQuantity(...) kald blot (SELECT ReturnValue FROM dbo.GetBatchReleaseQuantityTVP(...)) . Dette vil fungere væsentligt bedre og vil også undgå, at folk overfører ugyldige datoer til en varchar-parameter.



  1. Hvordan indstiller jeg ORDER BY-parametre ved hjælp af forberedt PDO-erklæring?

  2. HVOR vs AT HAVE

  3. Udfør øjeblikkelig med ikke-Sql-type

  4. Træk måneder fra en dato i PostgreSQL