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