sql >> Database >  >> RDS >> Sqlserver

Probleem met SQL-functie De laatste instructie die in een functie is opgenomen, moet een retourinstructie zijn

Zoals de fout suggereert, moet de laatste instructie een return-instructie zijn. In tegenstelling tot sommige andere talen is de stroom van de IF/ELSE statement wordt niet gecontroleerd tijdens compilatie, dus SQL Server weet niet dat een van de vertakkingen verplicht is (zelfs ELSE ). Aangezien dit niet is aangevinkt, is er geen manier om te weten of de functie een waarde zal retourneren, tenzij de laatste instructie een return-instructie is. Zelfs een eenvoudige functie als deze zal mislukken:

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

De oplossing is om gewoon de ELSE . te verwijderen :

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

END

De functie stopt de uitvoering wanneer deze de eerste RETURN . bereikt , dus de ELSE is sowieso niet vereist.

Dus je functie zou worden:

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

Ik kan echter niet zien hoe de functie goed zal presteren, en waarom je een date doorgeeft als een varchar is mij een raadsel. Geeft u niets om dingen die tussen 23:59:59 en middernacht zijn gemaakt?

Ik zou geneigd zijn om dit te refactoren als een inline tabelwaarde-functie, en datums op de juiste manier te gebruiken, bijvoorbeeld

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

Dan wanneer u dbo.GetBatchReleaseQuantity(...) . aanroept bel gewoon (SELECT ReturnValue FROM dbo.GetBatchReleaseQuantityTVP(...)) . Dit zal aanzienlijk beter presteren en zal ook voorkomen dat mensen ongeldige datums doorgeven aan een varchar-parameter.



  1. Alternatieve Oracle-stuurprogramma's voor .net

  2. Hoe upsert correct te doen in postgres 9.5

  3. De beste manier om dubbele gegevens te voorkomen bij het kopiëren van csv postgresql

  4. Waarom crasht deze pdo::mysql-code in Windows?