Почему добавление круглых скобок в 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)) )

Зачем это? Не означает ли утверждение OR, что одно или другое должно быть истинным? Что мне здесь не хватает?

Ответ 1

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

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

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

Ответ 2

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

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

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

A || B && C && D

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

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

Ответ 4

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

Ответ 5

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