为什么在SQL查询中添加括号会导致结果发生变化?

Sam*_* F. 15 sql parentheses

当我执行以下查询时,即使有11条匹配的记录,也没有按照写入的方式返回.但是,如果我删除第6行和第9行的括号,则按预期返回所有11条记录.

1  select obj_id, obj_title, UI_DISPLAYNAME
2  from PITS_OBJECT 
3  LEFT OUTER JOIN ui_displayname_view ON obj_create_ui_id = UI_ID  
4  where
5  /* w/ parens, no results, w/o parens, expected results */
6  (
7     Upper( UI_DISPLAYNAME ) LIKE Upper( '%smith%' )  
8     OR Upper( OBJ_TITLE ) LIKE Upper( '%smith%' ) 
9  )
10 /* end w/ parents, no results.... */
11 AND OBJ_ID IN (select obj_id from PITS_OBJECT where 
12     (UPPER( OBJ_TITLE ) LIKE UPPER( '%smith%' )) 
13     AND obj_id in( select sa_obj_id as obj_id from security_access 
14         where sa_type_id = 494 
15         and sa_usrgrp_id = 35
16         and sa_usrgrp_type_id = 230 
17         union 
18         select sa_obj_id from security_access 
19         where sa_type_id = 494 
20         and sa_usrgrp_type_id = 231 
21         and sa_usrgrp_id in ( select ug_gi_id from user_group where ug_ui_id = 35)) )
Run Code Online (Sandbox Code Playgroud)

这为什么重要?OR声明是否意味着一个或另一个必须是真的?我在这里错过了什么?

ean*_*533 14

三个字:操作顺序.就像你在数学中学到的那样,某些运算符优先于其他运算符(比如在添加之前乘法),除非你使用括号强制它.在这种情况下,AND优先级高于OR.

如果不添加自己的括号,您的WHERE子句将被评估为:

Upper( UI_DISPLAYNAME ) LIKE Upper( '%smith%' )
OR 
(Upper( OBJ_TITLE ) LIKE Upper( '%smith%' ) 
    AND OBJ_ID IN (select obj_id from PITS_OBJECT where 
    ...)
Run Code Online (Sandbox Code Playgroud)

但是当您手动添加这些括号时,您将强制OR首先进行评估.

(Upper( UI_DISPLAYNAME ) LIKE Upper( '%smith%' )
    OR Upper( OBJ_TITLE ) LIKE Upper( '%smith%' ))
AND OBJ_ID IN (select obj_id from PITS_OBJECT where 
...
Run Code Online (Sandbox Code Playgroud)

编辑:我应该直接回答您关于为什么要获得更多数据的问题.原因是,如果没有括号,如果发现第7行为真,引擎会将其检查短路.换句话说,它将包括所有记录Upper( UI_DISPLAYNAME ) LIKE Upper( '%smith%' ),而不管其他标准.

当您添加这些括号时,逻辑会更改.它将包括记录where Upper( UI_DISPLAYNAME ) LIKE Upper( '%smith%' ) OR Upper( OBJ_TITLE ) LIKE Upper( '%smith%' ),然后它检查记录ALSO是否满足从第12行开始的内部选择.这些额外记录不会显示,因为它们不符合该内部选择的标准.


Pur*_*uit 14

您的where子句目前类似于以下内容:

(A || B) && C && D
Run Code Online (Sandbox Code Playgroud)

没有括号,如下

A || B && C && D
Run Code Online (Sandbox Code Playgroud)

这相当于

A || (B && (C && D))
Run Code Online (Sandbox Code Playgroud)

  • 实际上只有一个'A`,`B`和`C`.你看到的`D`实际上是从第12行开始的内部选择的一部分.由于SQL的格式化方式,很难分辨.不过,你仍然是正确的. (2认同)