根据参数动态切换 on/off WHERE 布尔表达式
Dynamically switching on/off WHERE boolean expression(s) based on a parameter
我在存储过程中使用 SQL Server 2012 SELECT
。 SP 有很多参数。其中一个参数在我的问题中很重要。这是我的 SP 的伪代码:
create proc MyProc
@mid tinyint,
@param1 bit = 0
as
set nocount on
select
p.RowId,
i.Sku,
i.Condition,
p.OldPrice,
p.Delta
from Prices p
join Items i on (p.Sku = i.Sku)
where
(p.Mid = @mid)
and (i.Quantity > 0)
and (i.IsNew = 0)
--The condition below must (not)execute depending on param1
----------------------------------------------------------------------
and not (p.Delta = 0 and p.CurrentPrice = p.pMin)
----------------------------------------------------------------------
and p.ThreadId = @thread_id
order by p.Delta desc
换句话说,如果 param1 = 0
查询执行 WITH 条件,如果 param1 = 1
则条件被忽略(就像它根本不存在一样!)。
我试着玩布尔表达式,但我还是不明白。
P.S。我不想要像本文中那样的任何动态 SQL:Building dynamic where condition in SQL statement。我喜欢我的预编译 SP。
只需在您的 where 子句中包含一个检查,这样 if when @param1 = 1
那么您不关心您希望忽略的条件。
((@param1 = 1) or not (p.Delta = 0 and p.CurrentPrice = p.pMin))
让我们以 @param1 = 0
为例:
==> ((0 = 1) or not (p.Delta = 0 and p.CurrentPrice = p.pMin))
==> (false or not (p.Delta = 0 and p.CurrentPrice = p.pMin))
==> not (p.Delta = 0 and p.CurrentPrice = p.pMin)
现在让我们以 @param1 = 1
为例:
==> ((1 = 1) or not (p.Delta = 0 and p.CurrentPrice = p.pMin))
==> (true or not (p.Delta = 0 and p.CurrentPrice = p.pMin))
==> true
完整修改语句:
create proc MyProc
@mid tinyint,
@param1 bit = 0
as
set nocount on
select
p.RowId,
i.Sku,
i.Condition,
p.OldPrice,
p.Delta
from Prices p
join Items i on (p.Sku = i.Sku)
where
(p.Mid = @mid)
and (i.Quantity > 0)
and (i.IsNew = 0)
and ((@param1 = 1) or not (p.Delta = 0 and p.CurrentPrice = p.pMin))
and p.ThreadId = @thread_id
order by p.Delta desc
你可以使用or条件来实现,如果or中的第一个语句的计算结果为真,则不会尝试第二个
.....
where @param1 = 1 or
(
p.Mid = @mid
and i.Quantity > 0
and i.IsNew = 0
)
只需在 WHERE 子句中包含另一个条件,如果 param1
为 1,则整个表达式的计算结果为 TRUE。 OR
运算符是一种非常方便的方法。
AND ( @param1 = 1 OR ( NOT ( p.Delta = 0 AND p.CurrentPrice = p.pMin ) )
当 @param1 = 1
的计算结果为 TRUE 时,OR
后面的表达式的计算结果是什么并不重要... TRUE、FALSE 或 NULL/ 这无关紧要,因为所有三个这些:1) “TRUE OR FALSE
”,2) “TRUE OR NULL
”,和 3) “TRUE OR TRUE
”计算为 TRUE
.
请注意,这并不能保证我们永远不会计算 OR
之后的表达式。我们可以说,当 @param1 = 1
为 TRUE 时,OR
后面的表达式的 result 将被忽略。但是 SQL 服务器可以自由计算 OR
之后的表达式。我们无法控制这一点。
在某些情况下,评估可能会引发错误。所以从这个意义上说,表达并没有完全消失。在这个特定的例子中,我没有看到表达式可能会抛出什么错误,但这主要是因为我没有看到列的数据类型,而且我不知道什么隐式数据类型转换 SQL 服务器可能正在表演。
至于将 BIT
类型作为参数传递,我不熟悉其中的细微差别。
但我建议我们在 SQL
中明确进行数据类型转换
AND ( @param1 = CAST(1 AS BIT) OR ( NOT ( p.Delta = 0 AND p.CurrentPrice = p.pMin ) )
我在存储过程中使用 SQL Server 2012 SELECT
。 SP 有很多参数。其中一个参数在我的问题中很重要。这是我的 SP 的伪代码:
create proc MyProc
@mid tinyint,
@param1 bit = 0
as
set nocount on
select
p.RowId,
i.Sku,
i.Condition,
p.OldPrice,
p.Delta
from Prices p
join Items i on (p.Sku = i.Sku)
where
(p.Mid = @mid)
and (i.Quantity > 0)
and (i.IsNew = 0)
--The condition below must (not)execute depending on param1
----------------------------------------------------------------------
and not (p.Delta = 0 and p.CurrentPrice = p.pMin)
----------------------------------------------------------------------
and p.ThreadId = @thread_id
order by p.Delta desc
换句话说,如果 param1 = 0
查询执行 WITH 条件,如果 param1 = 1
则条件被忽略(就像它根本不存在一样!)。
我试着玩布尔表达式,但我还是不明白。
P.S。我不想要像本文中那样的任何动态 SQL:Building dynamic where condition in SQL statement。我喜欢我的预编译 SP。
只需在您的 where 子句中包含一个检查,这样 if when @param1 = 1
那么您不关心您希望忽略的条件。
((@param1 = 1) or not (p.Delta = 0 and p.CurrentPrice = p.pMin))
让我们以 @param1 = 0
为例:
==> ((0 = 1) or not (p.Delta = 0 and p.CurrentPrice = p.pMin))
==> (false or not (p.Delta = 0 and p.CurrentPrice = p.pMin))
==> not (p.Delta = 0 and p.CurrentPrice = p.pMin)
现在让我们以 @param1 = 1
为例:
==> ((1 = 1) or not (p.Delta = 0 and p.CurrentPrice = p.pMin))
==> (true or not (p.Delta = 0 and p.CurrentPrice = p.pMin))
==> true
完整修改语句:
create proc MyProc
@mid tinyint,
@param1 bit = 0
as
set nocount on
select
p.RowId,
i.Sku,
i.Condition,
p.OldPrice,
p.Delta
from Prices p
join Items i on (p.Sku = i.Sku)
where
(p.Mid = @mid)
and (i.Quantity > 0)
and (i.IsNew = 0)
and ((@param1 = 1) or not (p.Delta = 0 and p.CurrentPrice = p.pMin))
and p.ThreadId = @thread_id
order by p.Delta desc
你可以使用or条件来实现,如果or中的第一个语句的计算结果为真,则不会尝试第二个
.....
where @param1 = 1 or
(
p.Mid = @mid
and i.Quantity > 0
and i.IsNew = 0
)
只需在 WHERE 子句中包含另一个条件,如果 param1
为 1,则整个表达式的计算结果为 TRUE。 OR
运算符是一种非常方便的方法。
AND ( @param1 = 1 OR ( NOT ( p.Delta = 0 AND p.CurrentPrice = p.pMin ) )
当 @param1 = 1
的计算结果为 TRUE 时,OR
后面的表达式的计算结果是什么并不重要... TRUE、FALSE 或 NULL/ 这无关紧要,因为所有三个这些:1) “TRUE OR FALSE
”,2) “TRUE OR NULL
”,和 3) “TRUE OR TRUE
”计算为 TRUE
.
请注意,这并不能保证我们永远不会计算 OR
之后的表达式。我们可以说,当 @param1 = 1
为 TRUE 时,OR
后面的表达式的 result 将被忽略。但是 SQL 服务器可以自由计算 OR
之后的表达式。我们无法控制这一点。
在某些情况下,评估可能会引发错误。所以从这个意义上说,表达并没有完全消失。在这个特定的例子中,我没有看到表达式可能会抛出什么错误,但这主要是因为我没有看到列的数据类型,而且我不知道什么隐式数据类型转换 SQL 服务器可能正在表演。
至于将 BIT
类型作为参数传递,我不熟悉其中的细微差别。
但我建议我们在 SQL
中明确进行数据类型转换 AND ( @param1 = CAST(1 AS BIT) OR ( NOT ( p.Delta = 0 AND p.CurrentPrice = p.pMin ) )