Oracle - 当我使用 EXISTS 时,关系运算符无效
Posted
技术标签:
【中文标题】Oracle - 当我使用 EXISTS 时,关系运算符无效【英文标题】:Oracle - Invalid relational operator when I'm using EXISTS 【发布时间】:2020-05-01 18:04:23 【问题描述】:我收到了以下查询,当满足条件时,从表 et_fact_reclam_ter_his_misc 中删除返回的记录:
DELETE FROM et_fact_reclam_ter_his_misc
WHERE num_siniest || num_exped IN
(SELECT DISTINCT num_siniest || num_exped
FROM et_fact_reclam_ter_his_misc t1
WHERE NOT EXISTS (SELECT *
FROM et_fact_reclam_ter_misc t2
WHERE t1.num_siniest = t2.num_siniest));
我一直在搜索,发现使用EXISTS
而不是IN
会提高查询性能。但是我遇到了2个错误。第一个是当我将IN
运算符替换为EXISTS
时出现的错误消息:
DELETE FROM et_fact_reclam_ter_his_misc
WHERE num_siniest || num_exped EXISTS
(SELECT DISTINCT num_siniest || num_exped
FROM et_fact_reclam_ter_his_misc t1
WHERE NOT EXISTS (SELECT *
FROM et_fact_reclam_ter_misc t2
WHERE t1.num_siniest = t2.num_siniest));
ORA-00920: invalid relational operator
第二个是当我尝试在DELETE
内嵌套一个SELECT
,但返回的行数不同:
DELETE FROM et_fact_reclam_ter_his_misc
WHERE EXISTS
(SELECT FROM et_fact_reclam_ter_his_misc
WHERE num_siniest || num_exped IN
(SELECT DISTINCT num_siniest || num_exped
FROM et_fact_reclam_ter_his_misc t1
WHERE NOT EXISTS
(SELECT *
FROM et_fact_reclam_ter_misc t2
WHERE t1.num_siniest = t2.num_siniest)));
感谢任何有助于提高查询性能的帮助
【问题讨论】:
如果您可以随约束/索引一起描述表格,则可以即兴创作。还需要每个表中的记录数和被删除的记录数 您可以尝试每个查询和反馈。 我一直在搜索,发现使用 EXISTS 代替 IN 可以提高查询性能。 你从哪里读到的?不会的。 【参考方案1】:您可以尝试下面的方法,而不是连接字段以进行连接的最佳方法,
DELETE FROM et_fact_reclam_ter_his_misc A
WHERE EXISTS
( SELECT 1 FROM
(SELECT DISTINCT num_siniest || num_exped
FROM et_fact_reclam_ter_his_misc t1) B
WHERE A.num_siniest|| A.num_exped = B.num_siniest || B.num_exped
AND NOT EXISTS (SELECT 1
FROM et_fact_reclam_ter_misc t2
WHERE B.num_siniest = t2.num_siniest));
似乎连接的列是数字,它会强制 oracle 将其强制转换为 char,这可能会影响性能。如果您要处理大量记录,那么下面的列应该会更快。
DELETE FROM et_fact_reclam_ter_his_misc A
WHERE EXISTS
( SELECT 1 FROM
(SELECT DISTINCT num_siniest, num_exped
FROM et_fact_reclam_ter_his_misc t1) B
WHERE A.num_siniest = B.num_siniest
AND A.num_exped = B.num_exped
AND NOT EXISTS (SELECT 1
FROM et_fact_reclam_ter_misc t2
WHERE B.num_siniest = t2.num_siniest));
DISTINCT 会矫枉过正,用 group by 代替肯定会好得多,所以最好的是:
DELETE FROM et_fact_reclam_ter_his_misc A
WHERE EXISTS
( SELECT 1 FROM
(SELECT num_siniest, num_exped,count(1)
FROM et_fact_reclam_ter_his_misc t1
group by num_siniest, num_exped) B
WHERE A.num_siniest = B.num_siniest
AND A.num_exped = B.num_exped
AND NOT EXISTS (SELECT 1
FROM et_fact_reclam_ter_misc t2
WHERE B.num_siniest = t2.num_siniest));
【讨论】:
【参考方案2】:看起来可以这样做:
delete et_fact_reclam_ter_his_misc t1
where not exists
( select * from et_fact_reclam_ter_misc t2
where t2.num_siniest = t1.num_siniest
);
在原始版本中,第一级子查询似乎是在查询被删除的同一张表,只是为了构造一个not exists
子查询。我怀疑您要做的就是删除主表中不存在num_siniest
的his
行。一些示例数据和预期结果会让这一点更清楚。
【讨论】:
以上是关于Oracle - 当我使用 EXISTS 时,关系运算符无效的主要内容,如果未能解决你的问题,请参考以下文章
Oracle where exists 子句不适用于 SQL Plus
检查架构中的 IF 表 EXISTS 时发生 Oracle PL/SQL 过程错误 [重复]