Oracle查询:仅存在一个记录时,WHERE NOT LIKE不排除记录

问题描述

我有以下查询

select cand_id 
from cand_kw
WHERE client_id='mamasandpapas' AND UPPER(kw) LIKE '%MaraH%' OR UPPER(kw) LIKE '%ANDREW%' AND UPPER(kw) NOT LIKE '%KOCH%' 

数据库中包含以下记录:

Andrew Postings
Andrew Postings
Andrew McDee
Marah Koch

因此,其中有安德鲁(Andrew)的三行,但其中只有马拉(Marah)的记录。

如果我将查询更改为以下内容,则将两个Andrew帖子排除在外

select cand_id
from cand_kw
 WHERE client_id='mamasandpapas' AND UPPER(kw) LIKE '%MaraH%' OR UPPER(kw) LIKE '%ANDREW%' AND UPPER(kw) NOT LIKE '%POSTINGS%' 

因此,看起来好像只有一条记录存在,即使将结果排除在外,也会返回结果。

这使用的是Oracle(9i)的非常旧的版本,其搜索(kw)字段代表关键字,并且是包含一堆关键字的CLOB。

这是我设计的非常老的系统。

在第一种情况下,谁能解释为什么不排除Marah Koch而将Andrew Posts记录排除在外?

解决方法

大概,您打算使用类似where的子句:

WHERE client_id = 'mamasandpapas' AND
      (UPPER(kw) LIKE '%MARAH%' OR UPPER(kw) LIKE '%ANDREW%' AND UPPER(kw) NOT LIKE '%KOCH%')

但是我不确定,因为您没有解释要实现的实际逻辑。也就是说,如果您要混合使用ANDOR,请使用括号-至少要等到您真正了解运算符的优先级之后。

,

编写方式,仅当“%ANDREW%”的评估结果为True时,才会评估“不喜欢”的“%KOCH%”。这是关于Marah Koch记录的原始WHERE子句的流程。

第一个SQL查看client_id是否为'mamasandpapas'。太好了!接下来,它看到一个AND,这意味着WHERE子句为true时必须遵循的所有条件也必须为真,幸运的是,Upper(kw)确实像'%MARAH%'。然后,接下来看到“或”。 SQL决定它可以忽略其余部分,因为如果OR两侧的任何表达式的求值都为true,那么它就已经完成求值,因为Upper(kw)LIKE'%MARAH%'已经求值为true,所以它甚至都没有达到Upper (kw)不喜欢'%KOCH%'。

同样,在您的第二个WHERE子句示例中,它似乎仅能工作,因为在Andrew Postings的情况下,在client_id评估为true之后,AND会说Upper(kw)是否为LIKE'%MARAH%',哦不是,现在我们移至OR的另一侧,Upper(kw)为LIKE'%ANDREW%',但请稍等,现在我看到一个AND,这意味着Upper(kw)就像'%ANDREW%'另一方面,“ WHERE”必须为真。如果您将记录添加到您的Marah Posts表中,该记录仍将在第二个示例中返回。

为此我学到的术语是“裸OR”。换句话说,为便于阅读,最好用括号将所有OR语句“修饰”,因为这是大多数人理解AND和OR逻辑的方式。