删除语句不适用于oracle中的查询
Posted
技术标签:
【中文标题】删除语句不适用于oracle中的查询【英文标题】:Delete statement not working on query in oracle 【发布时间】:2020-07-09 06:25:05 【问题描述】:我有一张桌子BK_178_ABC
。我只想在满足某些条件时对该表执行删除语句:
我在这张桌子上的总数是:
select count(*) from BK_178_ABC; ==>22024727
我在下面有这个条件,如果满足,那么我需要从这个 BK_178_ABC 表中删除。所以,我首先计算了要删除的总行数。所以,我尝试了下面的语句。
SELECT Count(*)
FROM
BK_178_ABC a
LEFT JOIN
(SELECT * FROM xyz WHERE UPPER(type) = 'MOOV' AND UPPER(buyer) = 'KERA') gr
ON
SubStr (a.PS_UNIQUE_ID,-8) = gr.SOURCEID
LEFT JOIN
(SELECT * FROM xyz WHERE UPPER(type) = 'MOOV' AND UPPER(buyer) = 'KERA') gr2
ON
a.GROUP_NBR = gr2.SOURCEID
WHERE EXISTS
(
SELECT 1 FROM droptable drp
WHERE
COALESCE(gr.ROLLUPGROUPID, gr2.ROLLUPGROUPID, SubStr(a.ps_unique_id,-8))=drp.groupid
);
所以,要删除的计数是:2902563。
我尝试了两个删除语句,但它们都给了我错误的计数。因为,我的预期计数是 2902563,但我没有得到正确的结果。
DELETE FROM bk_178_abc WHERE EXISTS (SELECT 1
FROM bk_178_abc a
LEFT JOIN (SELECT *
FROM xyz
WHERE Upper(type) = 'MOOV'
AND Upper(buyer) = 'KERA') gr
ON Substr (a.ps_unique_id, -8) = gr.sourceid
LEFT JOIN (SELECT *
FROM xyz
WHERE Upper(type) = 'MOOV'
AND Upper(buyer) = 'KERA') gr2
ON a.group_nbr = gr2.sourceid
WHERE EXISTS (SELECT 1
FROM droptable drp
WHERE COALESCE(gr.rollupgroupid,
gr2.rollupgroupid,
Substr(a.ps_unique_id, -8)) = drp.groupid))
;
它,清空了整个表,因为我看到的删除总数是:22024727
所以,我再次重构了上面的代码,尝试了另一个删除语句:
DECLARE
begin
DELETE FROM BK_178_ABC a WHERE EXISTS (SELECT 1 FROM (SELECT * FROM xyz WHERE UPPER(type) = 'MOOV' AND UPPER(buyer) = 'KERA') gr,
xyz gr2,
droptable drp WHERE SubStr (a.PS_UNIQUE_ID,-8) = gr.SOURCEID AND a.GROUP_NBR = gr.SOURCEID
AND COALESCE(gr.ROLLUPGROUPID, gr2.ROLLUPGROUPID, SubStr(a.ps_unique_id,-8))=drp.groupid );
Dbms_Output.put_line(SQL%ROWCOUNT);
END;
我看到行数是零。我的sql语句有什么问题?
【问题讨论】:
【参考方案1】:您可以按如下方式使用 IN:
DELETE FROM bk_178_abc WHERE rowid in (SELECT a.rowid
FROM bk_178_abc a
LEFT JOIN (SELECT *
FROM xyz
WHERE Upper(type) = 'MOOV'
AND Upper(buyer) = 'KERA') gr
ON Substr (a.ps_unique_id, -8) = gr.sourceid
LEFT JOIN (SELECT *
FROM xyz
WHERE Upper(type) = 'MOOV'
AND Upper(buyer) = 'KERA') gr2
ON a.group_nbr = gr2.sourceid
WHERE EXISTS (SELECT 1
FROM droptable drp
WHERE COALESCE(gr.rollupgroupid,
gr2.rollupgroupid,
Substr(a.ps_unique_id, -8)) = drp.groupid))
;
【讨论】:
你能告诉我,如果我不写这个rowid,那么我的整个表都会被删除。为什么会这样?【参考方案2】:您可能希望使用性能更好的不同技术。在您的情况下,您可以使用 CTAS/TRUNCATE/BULK COLLECT,因为您想删除表中 10% 以上的行(2902563 of 22024727)。以我的经验,当您想要消除超过 10% 的行或表,并且数量超过一百万时,这种技术会更快。但是,请注意 INSERT APPEND 会锁定表,因为它是直接路径操作。
这种技术的近似值是
alter session enable parallel dml ;
alter session enable parallel ddl ;
alter session force parallel query ;
create table res_bk_178_abc parallel compress
for
select * FROM bk_178_abc WHERE rowid in (SELECT a.rowid
FROM bk_178_abc a
LEFT JOIN (SELECT *
FROM xyz
WHERE Upper(type) = 'MOOV'
AND Upper(buyer) = 'KERA') gr
ON Substr (a.ps_unique_id, -8) = gr.sourceid
LEFT JOIN (SELECT *
FROM xyz
WHERE Upper(type) = 'MOOV'
AND Upper(buyer) = 'KERA') gr2
ON a.group_nbr = gr2.sourceid
WHERE EXISTS (SELECT 1
FROM droptable drp
WHERE COALESCE(gr.rollupgroupid,
gr2.rollupgroupid,
Substr(a.ps_unique_id, -8)) = drp.groupid)) ;
truncate table bk_178_abc reuse storage;
insert /*+append parallel(a) */ into bk_178_abc a select /*+parallel(b) */ * from res_bk_178_abc b;
commit;
drop table res_bk_178_abc purge;
基本上,在这种情况下,我没有删除近 300 万行或 22 行(这很昂贵),而是创建一个包含我想要保留的行的表,截断原始行,然后使用直接路径操作插入回数据并行启用。
在 create table as select (CTAS) 中,您可以使用提示来强制执行并行查询,但由于我不知道您的数据模型以及这些表上有多少索引,所以我没有触及那部分。 @Tajesh 正确地包含了 rowid 引用以仅获取必须删除的行数。
问候
【讨论】:
以上是关于删除语句不适用于oracle中的查询的主要内容,如果未能解决你的问题,请参考以下文章
MySQL 查询适用于 SELECT 但不适用于 UPDATE 语句