sql - 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
因此,其中有 3 行和 Andrew,但只有一个记录有 Marah。
如果我将查询更改为以下内容,则排除两个 Andrew Postings
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 Postings 记录被排除在外吗?
解决方案
按照它的编写方式,NOT LIKE "%KOCH%" 只会在 LIKE "%ANDREW%" 评估为 True 时评估。这是关于与 Marah Koch 的记录的原始 WHERE 子句的流程。
第一个 SQL 查看 client_id 是否为“mamasandpapas”。太好了!接下来,它看到一个 AND,这意味着它后面的任何内容也必须为真,WHERE 子句才为真,幸运的是,Upper(kw) 确实是 LIKE '%MARAH%'。然后它会看到 OR next。SQL 决定它可以忽略其余部分,因为如果 OR 任一侧的任何表达式计算为真,那么它就完成了计算,因为 Upper(kw) LIKE '%MARAH%' 已经计算为真,所以它甚至没有到达 Upper (kw) 不喜欢 '%KOCH%'。
同样,在您的第二个 WHERE 子句示例中,它似乎仅起作用,因为在 Andrew Postings 的情况下,在 client_id 评估为 true 后,AND 说查看 Upper(kw) 是否为 LIKE'%MARAH%',哦不是,现在我们移动到 OR 的另一边,Upper(kw) is LIKE '%ANDREW%' 但是等等,现在我看到一个 AND,这意味着 Upper(kw) LIKE'%ANDREW%' 和上面的任何东西另一方必须为真,WHERE 为真。如果您在 Marah Postings 表中添加一条记录,它仍将在第二个示例中返回。
我为此学到的术语是“Naked ORs”。换句话说,为了可读性和大多数人理解 AND 和 OR 的逻辑,最好用括号“修饰”任何 OR 语句。
推荐阅读
- scala - 没有参数的scala uanpply
- x86 - 在 Solaris x86 平台上覆盖 mapfile 中的 hwcap_2
- jquery - Jquery如果数组推送值中的变量
- javascript - Vuex 延迟提交/缓冲状态更改
- jquery - 在 Internet Explorer 中调试一行 JQuery
- cygwin - 无法在 cygwin 中使用命令“iconv”转换以下文件:“udhr_deu_1901.txt”(来源:https://unicode.org/udhr/d/udhr_deu_1901.txt)
- javascript - 将 http 流量发送到多个域的 HTTPS
- postgresql - Thingsboard 无法连接到外部数据库 postgresql 谷歌云
- c# - 如何仅使用组合来模拟虚拟方法?
- c# - C# PInvoke 传递出 unsigned char*