where condition 在错误的地方有一个声明的变量不知道它是否有效
where condition have a declared variable on a wrong place do not know if its valid
我的一个大存储过程中有如下这样的语句,我想知道这样写是否有效。
SELECT @PVDate = pv.Date,
@PVdMBeginDate = dbo.fPVoidDate(pv.myID)
FROM PVMeter pv (NOLOCK)
WHERE pv.PR_ID = @PR_ID
AND @VCommen BETWEEN pv.PVDMDate AND dbo.fPVoidDate(pv.myID)
现在,在这里,我的问题是,@VCommen 是一个声明的日期变量,上面设置了一个值。它根本不是PVMeter的一列,而PVDMDate是PVMeter和fpVoidDate中的一列returns datetime
当我调试 SP 时,我没有看到 @PVDate 和 @PVDMBeginDate 上的值
原始查询等同于:
SELECT
@PVDate = pv.Date,
@PVdMBeginDate = dbo.fPVoidDate(pv.myID)
FROM PVMeter pv (NOLOCK)
WHERE
pv.PR_ID = @PR_ID
AND pv.PVDMDate <= @VCommen
AND @VCommen <= dbo.fPVoidDate(pv.myID)
这种风格大家应该比较熟悉吧。通常,您可以在 WHERE
子句中放置任何表达式,它可以由变量或常量构成,而根本不引用 table 列。
例子
经典示例:WHERE 1=1 ...
动态生成查询文本时。可以很容易地添加任意数量的表达式,没有特定的顺序,并在所有表达式前加上 AND
.
DECLARE @VarSQL nvarchar(max);
SET @VarSQL = 'SELECT ... FROM ... WHERE 1=1 ';
IF ... THEN SET @VarSQL = @VarSQL + ' AND expression1';
IF ... THEN SET @VarSQL = @VarSQL + ' AND expression2';
IF ... THEN SET @VarSQL = @VarSQL + ' AND expression3';
EXEC @VarSQL;
因此您不需要复杂的逻辑来确定是否需要在每个表达式前添加 AND
。
另一个例子。
您有一个带有参数 @ParamID int
的存储过程。
您在过程中有一个复杂的查询,通常 return 结果集的许多行和一列是唯一的 ID
。
SELECT ID, ...
FROM ...
WHERE
expression1
AND expression2
AND expression3
...
如果 @ParamID
是 NULL
,您想要 return 所有行,如果 @ParamID
不是 [=21],则只有给定 ID
的一行=].我个人使用这种方法。当我第一次打开显示查询结果的屏幕时,我想向用户显示所有行,所以我将 NULL
作为参数传递。然后用户对选定的行进行更改,这是通过单独的 UPDATE
语句完成的。然后我想刷新用户在屏幕上看到的结果。我知道刚刚更改的行的 ID
,所以我只需要重新查询这一行,所以我将这个 ID
传递给过程并再次获取一行而不是整个 table .
最终查询如下所示:
SELECT ID, ...
FROM ...
WHERE
(@ParamID IS NULL OR ID = @ParamID)
AND expression1
AND expression2
AND expression3
...
OPTION (RECOMPILE);
因此我不必重复查询的复杂代码两次。
我的一个大存储过程中有如下这样的语句,我想知道这样写是否有效。
SELECT @PVDate = pv.Date,
@PVdMBeginDate = dbo.fPVoidDate(pv.myID)
FROM PVMeter pv (NOLOCK)
WHERE pv.PR_ID = @PR_ID
AND @VCommen BETWEEN pv.PVDMDate AND dbo.fPVoidDate(pv.myID)
现在,在这里,我的问题是,@VCommen 是一个声明的日期变量,上面设置了一个值。它根本不是PVMeter的一列,而PVDMDate是PVMeter和fpVoidDate中的一列returns datetime
当我调试 SP 时,我没有看到 @PVDate 和 @PVDMBeginDate 上的值
原始查询等同于:
SELECT
@PVDate = pv.Date,
@PVdMBeginDate = dbo.fPVoidDate(pv.myID)
FROM PVMeter pv (NOLOCK)
WHERE
pv.PR_ID = @PR_ID
AND pv.PVDMDate <= @VCommen
AND @VCommen <= dbo.fPVoidDate(pv.myID)
这种风格大家应该比较熟悉吧。通常,您可以在 WHERE
子句中放置任何表达式,它可以由变量或常量构成,而根本不引用 table 列。
例子
经典示例:WHERE 1=1 ...
动态生成查询文本时。可以很容易地添加任意数量的表达式,没有特定的顺序,并在所有表达式前加上 AND
.
DECLARE @VarSQL nvarchar(max);
SET @VarSQL = 'SELECT ... FROM ... WHERE 1=1 ';
IF ... THEN SET @VarSQL = @VarSQL + ' AND expression1';
IF ... THEN SET @VarSQL = @VarSQL + ' AND expression2';
IF ... THEN SET @VarSQL = @VarSQL + ' AND expression3';
EXEC @VarSQL;
因此您不需要复杂的逻辑来确定是否需要在每个表达式前添加 AND
。
另一个例子。
您有一个带有参数 @ParamID int
的存储过程。
您在过程中有一个复杂的查询,通常 return 结果集的许多行和一列是唯一的 ID
。
SELECT ID, ...
FROM ...
WHERE
expression1
AND expression2
AND expression3
...
如果 @ParamID
是 NULL
,您想要 return 所有行,如果 @ParamID
不是 [=21],则只有给定 ID
的一行=].我个人使用这种方法。当我第一次打开显示查询结果的屏幕时,我想向用户显示所有行,所以我将 NULL
作为参数传递。然后用户对选定的行进行更改,这是通过单独的 UPDATE
语句完成的。然后我想刷新用户在屏幕上看到的结果。我知道刚刚更改的行的 ID
,所以我只需要重新查询这一行,所以我将这个 ID
传递给过程并再次获取一行而不是整个 table .
最终查询如下所示:
SELECT ID, ...
FROM ...
WHERE
(@ParamID IS NULL OR ID = @ParamID)
AND expression1
AND expression2
AND expression3
...
OPTION (RECOMPILE);
因此我不必重复查询的复杂代码两次。