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.