Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Problem z funkcją Sql Ostatnia instrukcja zawarta w funkcji musi być instrukcją return

Jak sugeruje błąd, ostatnia instrukcja musi być zwrotem. W przeciwieństwie do innych języków przepływ IF/ELSE instrukcja nie jest sprawdzana podczas kompilacji, więc SQL Server nie wie, że jedna z gałęzi jest obowiązkowa (nawet ELSE ). Ponieważ nie jest to zaznaczone, nie ma możliwości sprawdzenia, czy funkcja zwróci wartość, chyba że ostatnia instrukcja jest instrukcją powrotu. Nawet prosta funkcja, taka jak ta, zawiedzie:

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

Rozwiązaniem jest po prostu usunięcie ELSE :

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

END

Funkcja zatrzyma wykonywanie, gdy osiągnie pierwszy RETURN , więc ELSE i tak nie jest wymagane.

Twoja funkcja stałaby się więc:

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

Nie widzę jednak, jak ta funkcja będzie działać dobrze i dlaczego podajesz datę jako varchar, jest poza mną. Nie przejmujesz się rzeczami, które powstały między 23:59:59 a północą?

Skłonny byłbym przerobić to na wbudowaną funkcję z wartościami tabelarycznymi i właściwie używać dat, np.

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

Następnie za każdym razem, gdy wywołasz dbo.GetBatchReleaseQuantity(...) po prostu wywołaj (SELECT ReturnValue FROM dbo.GetBatchReleaseQuantityTVP(...)) . Będzie to działać znacznie lepiej, a także pozwoli uniknąć przekazywania nieprawidłowych dat do parametru varchar.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak uzyskać listę kolumn z unikalnymi ograniczeniami w bazie danych SQL Server — samouczek SQL Server / TSQL część 98?

  2. Funkcja agregująca sql do uzyskania listy

  3. Liczba serwerów SQL jest powolna

  4. Lista typów danych w SQL Server 2017

  5. Jak zlokalizować zadania agenta programu SQL Server w Azure Data Studio