PostgreSQL按前缀条件删除数据时逻辑运算符OR改AND的疑问
逻辑转换的核心原理
这是逻辑运算里的德摩根定律的典型应用:对多个条件的「或(OR)」关系整体取否定时,需要把每个条件单独取反,同时把原来的OR运算符替换为AND,公式表达为:
NOT (A OR B OR C) = NOT A AND NOT B AND NOT C
对应业务场景拆解
你需要保留的记录满足的条件是:substr(serial_number, 1, 2) = '01' OR substr(serial_number, 1, 2) = '02' OR substr(serial_number, 1, 2) = '03'
你要删除的是不符合保留规则的记录,也就是对上面整个保留条件取反,按德摩根定律展开后就是:substr(serial_number, 1, 2) != '01' AND substr(serial_number, 1, 2) != '02' AND substr(serial_number, 1, 2) != '03'
这就是你需要把OR改成AND的原因。
为什么错误写法会删掉全部数据
我们拿一条需要保留的01A记录验证错误的OR条件:
条件为NOT LIKE '01' OR NOT LIKE '02' OR NOT LIKE '03'
01不满足NOT LIKE '01',结果为false- 但
01肯定不等于02,所以NOT LIKE '02'结果为true
OR运算只要有一个条件为true,整体结果就为true,所以这条本该保留的记录也命中了删除条件,同理所有01/02/03开头的记录都会命中其中一个NOT LIKE条件,最终全部数据被删除。
多个否定条件用AND为什么能成立
我们还是拿需要删除的04A记录验证:
04不是01→ 结果true04不是02→ 结果true04不是03→ 结果true
三个条件同时为true,AND运算整体结果为true,成功命中删除规则。
而如果是需要保留的01A,第一个条件不是01就为false,AND运算只要有一个false整体就为false,不会被删除,完全符合业务预期。
更简洁的优化写法
不用写多个重复的OR/AND,用IN运算符可以避免逻辑写错:
-- 查询保留的记录 SELECT * FROM my_table WHERE substr(serial_number, 1, 2) IN ('01', '02', '03'); -- 直接删除不符合要求的记录 DELETE FROM my_table WHERE substr(serial_number, 1, 2) NOT IN ('01', '02', '03');
内容的提问来源于stack exchange,提问作者GeoGyro
相关产品推荐
相关产品推荐

