使用SELECT在SQL Server

时间:2015-08-30 06:53:31

标签: sql sql-server tsql variables stored-procedures

我有一个相当长的存储过程,它接受输入参数,根据一系列条件执行计算和操作,然后返回输出参数。

有问题的部分是一个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是否不能处理这种类型的相互依赖变量?

1 个答案:

答案 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