我有一个存储过程正在调用两个其他存储过程,它们返回正确的值并且非零。
我已经尽一切努力在这个问题上找到了
ALTER PROCEDURE [dbo].[updateBudgetCalc](@JobNum AS nvarchar(50))
AS
BEGIN
DECLARE @estHrs float
DECLARE @totHrs float
EXEC @totHrs = PanelShop.dbo.getHoursTotal @JobNum
EXEC @estHrs = PanelShop.dbo.getHoursEst @JobNum
UPDATE ActiveList SET PercentOfBudget = @estHrs/@totHrs WHERE Jobnum = @JobNum
return (@totHrs)
END;
执行此SP时,我得到:
消息8134,级别16,状态1,过程updateBudgetCalc,第14行 除以零错误。
它确实将@totHrs评估为null 然而,在结果中,我看到它查询了两个表并返回了totHrs的非零值2.22000 的estHrs值为5.25
答案 0 :(得分:6)
变量@estHrs
和@totHrs
保存执行嵌套存储过程的结果。如果执行时没有错误,则这些结果将为0
,这就是您Divide by zero
错误的原因。
重要的是要使存储过程的执行结果与该过程返回的结果集有所不同。
如果要从存储过程返回单个值,请使用output parameter。如果您的过程返回了结果集,则可以将该结果插入表中并从该表中选择适当的值。
具有输出参数的存储过程:
CREATE PROCEDURE [uspOutputParameter]
@Param int OUTPUT
AS BEGIN
SET @Param = 1
END
DECLARE @err int
DECLARE @param int
EXECUTE @err = uspOutputParameter @Param OUTPUT
IF @err = 0 BEGIN
PRINT 'OK'
PRINT @Param
END
ELSE BEGIN
PRINT 'Error'
END
具有结果集的存储过程:
CREATE PROCEDURE [uspResultSet]
AS BEGIN
SELECT 1 AS Result
END
CREATE TABLE #Temp (Result int)
INSERT INTO #Temp (Result)
EXECUTE uspResultSet
SELECT *
FROM #Temp
答案 1 :(得分:1)
佐罗夫的解释不太正确。存储过程可以返回值。这些值是整数。没有显式的return
,存储过程将失败并返回NULL
。
设置存储过程并被类型误导是完全有效的:
create procedure f
as begin
return cast(2.3 as float)
end;
declare @f float;
exec @f = f;
print @f;
这返回什么?它返回2
。为什么?返回值为整数。 SQL Server将2.3转换为整数并将其返回。这是在存储过程调用中得到的。
很可能您返回的值介于0和1之间,并且这些值被截断为0
-导致被零除错误。
佐罗夫的解决方案是正确的。使用输出参数。