我有一个相当长的存储过程,它接受输入参数,根据一系列条件执行计算和操作,然后返回输出参数。
有问题的部分是一个SELECT语句,它将值分配给存储过程中的多个变量,但这些值是相互依赖的。
SELECT @varX = CASE WHEN @REC_CHANGE = 1 THEN VT.X ELSE @varX END
,@varY = CASE WHEN @REC_CHANGE = 1 THEN VT.Y ELSE @varY END
,@varZ = CASE WHEN @REC_CHANGE = 1 THEN VT.Y * VT.X ELSE @varX END
FROM VarTable VT
WHERE VT.ID = @myID
AND <....>
@REC_CHANGE变量确定要检查的记录是否与用户输入值不同。如果是这样,那么我们希望查询从表中分配值。如果没有,那么我们希望保留用户输入值。
我遇到的问题是第一个变量@varX总是接受用户输入值,而不是重新分配表中的值,即使其后的其他变量 从表中获取值。例如,当@REC_CHANGE = 1时,@ varY会从表中提取新值,但@varX不会。这些值都来自同一个表,来自具有WHERE子句中指示的相同ID的同一行。
正如您所看到的,@ REC_CHANGE的条件在分配之间没有区别,因此我无法理解为什么@varX将保持不变(用户输入值),而@varY会相应地更新。此外,因为后面的赋值依赖于@varX,它们有时会返回错误的值。
我很感激你们提供的任何指示。非常感谢![/ p>
编辑:作为一个注释,我已经检查了如果我将@varX赋值分离到具有完全相同条件的SELECT或SET语句中会发生什么,并且值会相应地更新。也就是说查询看起来像这样:
SELECT @varX = CASE WHEN @REC_CHANGE = 1 THEN VT.X ELSE @varX END
FROM VarTable VT
WHERE VT.ID = @myID
AND <....>;
SELECT @varY = CASE WHEN @REC_CHANGE = 1 THEN VT.Y ELSE @varY END
,@varZ = CASE WHEN @REC_CHANGE = 1 THEN VT.Y * VT.X ELSE @varX END
FROM VarTable VT
WHERE VT.ID = @myID
AND <....>;
这会返回正确的结果,这让我想知道SQL Server是否不能处理这种类型的相互依赖变量?
答案 0 :(得分:1)
你正在尝试的应该工作。这是我在SQL Server 2008上测试过的一个独立的示例,它提供了预期的结果。我会认为它可能是导致意外行为的查询的另一个元素。
DECLARE @REC_CHANGE AS bit
DECLARE @myID AS int
DECLARE @varX AS int
DECLARE @varY AS int
DECLARE @varZ AS int
SET @REC_CHANGE = 1
SET @myID = 1
SET @varX = 2
SET @varY = 3
SELECT @varX = CASE WHEN @REC_CHANGE = 1 THEN VT.X ELSE @varX END
, @varY = CASE WHEN @REC_CHANGE = 1 THEN VT.Y ELSE @varY END
, @varZ = CASE WHEN @REC_CHANGE = 1 THEN VT.Y * VT.X ELSE @varX END
FROM
(SELECT 1 AS ID, 5 AS X, 6 AS Y)
AS VT
WHERE @myID = VT.ID
SELECT @varX, @varY, @varZ
我建议在您的环境中测试上面的代码。如果它有效,则可能值得查看查询和表的其他元素。
一种可能的解决方案是在查询开始时将用户输入参数分配给“虚拟”参数。所以喜欢:
DECLARE @varXb AS int
SET @vaxXb = @varX