在下面的SQL函数中,我必须根据条件返回值,但它会抛出错误。
"函数中包含的最后一个语句必须是return 。声明"
请帮助我克服这个问题。
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
ELSE
BEGIN
RETURN(SElECT ISNULL( SUM( AcceptedQuantity),0.00) From GoodsReceivedNoteDetail GRND
LEFT OUTER JOIN GoodsReceivedNote GRN ON GRN.LocationID=@i_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
答案 0 :(得分:3)
函数期望在最后一行返回。 只需通过将结果赋值给变量@nReturn并在最后一行返回它来修改函数。
create 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
DECLARE @nReturn numeric(18,3)
IF (@i_ProductInFlow ='2')
BEGIN
SElECT @nReturn = 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
ELSE
BEGIN
SElECT @nReturn = ISNULL( SUM( AcceptedQuantity),0.00) From GoodsReceivedNoteDetail GRND
LEFT OUTER JOIN GoodsReceivedNote GRN ON GRN.LocationID=@i_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
RETURN @nReturn
END
答案 1 :(得分:2)
如错误所示,最后一个语句必须是return语句。与其他语言不同,编译期间不会检查IF/ELSE
语句的流,因此SQL Server不知道其中一个分支是必需的(即使ELSE
)。由于未检查此项,因此无法知道函数是否将返回值,除非最后一个语句是return语句。即使像这样的简单函数也会失败:
CREATE FUNCTION dbo.FlowTest()
RETURNS INT
AS
BEGIN
IF 1 = 1
BEGIN
RETURN 1;
END
ELSE
BEGIN
RETURN 0;
END
END
解决方案是删除ELSE
:
CREATE FUNCTION dbo.FlowTest()
RETURNS INT
AS
BEGIN
IF 1 = 1
BEGIN
RETURN 1;
END
-- ELSE REMOVED
RETURN 0;
END
如果到达第一个RETURN
,该函数将停止执行,因此无论如何都不需要ELSE
。
所以你的功能将成为:
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 GRN.LocationID=@i_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
我无法看到该功能如何表现良好,以及为什么你传递日期作为varchar是超出我的。你不关心23:59:59到午夜之间创造的东西吗?
我倾向于将其重构为内联表值函数,并正确使用日期,例如。
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 GRN.LocationID=@i_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'
);
然后,只要您拨打dbo.GetBatchReleaseQuantity(...)
,只需致电(SELECT ReturnValue FROM dbo.GetBatchReleaseQuantityTVP(...))
即可。这将显着改善,并且还可以避免人们将无效日期传递给varchar参数。
答案 2 :(得分:1)
您无法像在C ++或C#中那样从SQL函数返回。在FUNCTION
块的末尾应该只有一个return语句:
所以只需将返回值放在局部变量中,并在函数末尾使用RETURN
语句:
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
DECLARE @retval NUMERIC(18, 3)
IF (@i_ProductInFlow ='2')
BEGIN
SElECT @retval = 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
ELSE
BEGIN
SElECT @retval = ISNULL( SUM( AcceptedQuantity),0.00) From GoodsReceivedNoteDetail GRND
LEFT OUTER JOIN GoodsReceivedNote GRN ON GRN.LocationID=@i_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
RETURN @retval
END