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.