请解释此SQL语句如何选择所有column1
值。
所以我有参数值A,B和*
如果我传递@brand = '*'
,则此语句将返回column1
中的所有值:
SELECT *
FROM TABLE
WHERE (column1 = @brand OR @brand = '*')
我在考虑,@brand = '*'
然后它将@brand
指定为TRUE
,因此column1
中的任何内容都是true
,这就是为什么它返回column1
如果我通过A
,则只会返回A
个值,如果B
,则B
值。
答案 0 :(得分:3)
你的假设是正确的。它依次根据最简单的路径评估WHERE
语句中的子句。
所以,因为有OR
,它首先评估@brand ='*'
子句;如果它产生TRUE
,则WHERE
子句得到满足,并且不再进行进一步的比较。
如果它产生FALSE
,则它会计算表达式中的另一个子句:column1 = @brand
。
但是,我应该注意,这不是在SQL中执行此操作的正确方法,因为SQL Server不保证短路也不保证逻辑子句的执行顺序。它碰巧在你的情况下以这种方式工作,但不能保证。您应该将WHERE
子句更改为如下所示:
((@brand = '*') OR (@brand <> '*' AND column1 = @brand))
答案 1 :(得分:1)
此SQL语句如何工作?
你在逻辑上问吗?
SQL使用三值逻辑。每个单独的谓词都可以评估为真,假或未知。
您需要在示例中考虑OR
的真值表,以了解如何组合谓词以获得整体结果。
在WHERE
子句的上下文中,对于要在结果中返回的行,整个谓词必须求值为true
。
上面的真值表表明,只要知道其中一个谓词是真的就足够了。因此,如果第一个评估为真,则无需评估第二个。这被称为短路评估。
SQL Server不保证评估顺序或它将使用短路评估。
示例
DECLARE @Table TABLE (
column1 VARCHAR(50) PRIMARY KEY);
INSERT INTO @Table
VALUES ('brand1'),
('brand2'),
('brand3')
DECLARE @brand VARCHAR(50) = 'brand1'
SELECT *
FROM @Table
WHERE ( column1 = @brand
OR @brand = '*' );
执行计划显示以下内容
扫描整个表并在每行上评估谓词。 SQL Server可能会也可能不会按所示顺序评估条件,可能会也可能不会使用短路评估。此信息不会向我们公开。
返回一行 - 第一行。
<强>效率强>
上面查询的语义只是
SELECT *
FROM @Table
WHERE column1= 'brand1'
应该可以通过对支持主键的索引进行简单查找来评估 - 而不是扫描整个表。
从SQL Server 2008开始,您可以使用以下
DECLARE @brand VARCHAR(50) = 'brand1'
SELECT *
FROM @Table
WHERE (column1 = @brand OR @brand = '*')
OPTION (RECOMPILE)
这会在执行它之前重新编译语句,并且不会缓存执行计划。这意味着该计划可以考虑@brand
通过的具体值。
现在@brand = '*'
的比较在编译时完成,并确定为假,谓词简化为column1 = 'brand1'
- 允许索引寻找该特定值。