Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Problem mit SQL-Funktionen Die letzte in einer Funktion enthaltene Anweisung muss eine return-Anweisung sein

Wie der Fehler andeutet, muss die letzte Anweisung eine return-Anweisung sein. Im Gegensatz zu einigen anderen Sprachen ist der Ablauf des IF/ELSE Die Anweisung wird während der Kompilierung nicht überprüft, sodass SQL Server nicht weiß, dass einer der Zweige obligatorisch ist (sogar ELSE ). Da dies nicht überprüft wird, gibt es keine Möglichkeit zu wissen, ob die Funktion einen Wert zurückgeben wird, es sei denn, die letzte Anweisung ist eine return-Anweisung. Selbst eine einfache Funktion wie diese wird fehlschlagen:

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

Die Lösung besteht darin, einfach das ELSE zu entfernen :

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

END

Die Funktion stoppt die Ausführung, wenn sie den ersten RETURN erreicht , also das ELSE wird sowieso nicht benötigt.

Ihre Funktion würde also zu:

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

Ich kann jedoch nicht sehen, wie die Funktion gut funktionieren wird, und warum Sie ein Datum als Varchar übergeben, ist mir ein Rätsel. Interessieren Sie sich nicht für Dinge, die zwischen 23:59:59 und Mitternacht erstellt wurden?

Ich wäre geneigt, dies als Inline-Tabellenwertfunktion umzugestalten und Datumsangaben richtig zu verwenden, z. B.

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

Dann, wann immer Sie dbo.GetBatchReleaseQuantity(...) aufrufen würden rufen Sie einfach (SELECT ReturnValue FROM dbo.GetBatchReleaseQuantityTVP(...)) auf . Dadurch wird die Leistung erheblich verbessert und es wird auch vermieden, dass Personen ungültige Daten an einen varchar-Parameter übergeben.