Почему добавление круглых скобок в SQL-запрос приводит к изменению результатов?

когда я выполняю следующий запрос, даже если есть 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)) )

почему это важно? Разве утверждение " или " не означает, что то или другое должно быть истинным? Я что-то упускаю?

5 ответов


три слова: порядок операций. Это как вы узнали в математике, некоторые операторы имеют приоритет над другими (например, умножение перед добавлением), если вы не используете скобки, чтобы заставить его ваш путь. В этом случае 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 
    ...)

но когда вы вручную добавляете в эти скобки, вы заставляете 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 
...

Edit: я должен напрямую ответить на ваш вопрос о том, почему вы получаете больше данных. Причина в том, что без скобок двигатель закоротит свою проверку, если обнаружит, что строка 7 истинна. Другими словами, он будет включать все записи, где Upper( UI_DISPLAYNAME ) LIKE Upper( '%smith%' ), независимо от других критериев.

когда вы добавляете в эти скобки, логику изменения. Он будет включать записи, где Upper( UI_DISPLAYNAME ) LIKE Upper( '%smith%' ) OR Upper( OBJ_TITLE ) LIKE Upper( '%smith%' ), а затем он проверяет, что запись также удовлетворяет внутреннему выбору, который начинается в строке 12. Эти дополнительные записи не отображаются, потому что они не соответствуют критериям этого внутреннего выбора.


ваше предложение where в настоящее время аналогично следующему:

(A || B) && C && D

без скобок, это выглядит следующим образом

A || B && C && D

что эквивалентно

A || (B && (C && D))

Это связано с превалированием AND и OR операторы. AND имеет более высокий приоритет. http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/conditions001.htm#i1034834


потому что вы изменили оператор where, чтобы всегда возвращать записи, где Upper( OBJ_TITLE ) LIKE Upper( '%smith%' ) верно, независимо от вашего следующего и


Это основной порядок операций. Скобки означают, что все испытанное прежде всего проверяется. Значение, возвращаемое после оценки элементов в круглых скобках, будет использоваться для оценки остальных. Поскольку и имеет приоритет над OR, скобки заставляют SQL сначала оценивать ORs.