次のクエリを実行すると、一致するレコードが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ステートメントは、どちらかが真でなければならないことを意味しませんか?ここで何が欠けていますか?
3つの単語:操作の順序。数学で学んだように、括弧を使用して強制しない限り、特定の演算子が他の演算子よりも優先されます(乗算は加算の前に行われます)。この場合、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行目から始まる内部選択も満たしていることを確認します。これらの追加レコードは、その内部の基準を満たしていないため、表示されません。選択する。
現在、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ステートメントを変更して、次のANDに関係なく、Upper( OBJ_TITLE ) LIKE Upper( '%smith%' )
がtrueであるレコードを常に返すようにしたためです。
これが基本的な操作の順序です。括弧は、他のものがテストされる前にすべてがテストされることを意味します。括弧内の項目を評価した後に返された値は、残りを評価するために使用されます。 ANDはORよりも優先されるため、括弧はSQLにORを最初に評価させます。