2016-01-05 88 views
0

作为标题,我想在Oracle/PLSQL中创建一个过程来删除在某些列中共享相同值的行。我知道如何使用查询来实现它,但是如何使用过程来实现它?我必须使用任何循环吗?我很新PLSQL使用Oracle/PLSQL中的过程删除重复记录

请大家帮忙,多谢!

回答

1

如果你想要一个简单的过程,从一个特定的表中删除,你可以使用下面的代码:

CREATE OR REPLACE PROCEDURE DELETE_DUPLICATE AS 

BEGIN 

    FOR I IN (SELECT TAB.A, TAB.B, MIN(ROWID) RID 
       FROM DUPLICATE_TABLE TAB 
      GROUP BY TAB.A, TAB.B 
      HAVING COUNT(*) > 1) LOOP 

    DELETE FROM DUPLICATE_TABLE TAB 
    WHERE I.RID <> TAB.ROWID 
     AND TAB.A = I.A 
     AND TAB.B = I.B; 

    COMMIT; 

    END LOOP; 

END; 

这里DUPLICATE_TABLE是具有重复值的表。我们正在删除列A和B中具有相同值的行。

+0

非常感谢! –

0

如果你知道如何在SQL中完成它,最好在SQL中完成它。只有当您不能在SQL语句中编写特定任务时,或者在查询中存在性能问题,并且可以通过在PL/SQL中编写逻辑来改进(第二种情况非常罕见)时,才应使用PL/SQL。

如果要编写PL/SQL过程来进行参数化,以便可以传递任何表以删除重复项,那么这很有意义。您需要在过程中动态生成删除语句并使用execute immediate执行。

如果你的目的是学习PL/SQL,那么它就是编程语言,你需要花一些时间,就好像你在学习新的编程语言一样。

+0

不是一个真正的答案。应该是一个评论。 – Drumbeg

0

不建议将plsql用于可使用普通sql执行的操作。 只要你有一个sql和plsql的组合,你就可以在sql和plsql引擎之间切换。所以如果没有适当的要求就没有任何意义。

如果由于某种原因仍然需要这样做,您可以至少实施批量删除以减少一些开销。请参考下面的代码,找出如何做到这一点 -

DECLARE 
TYPE t_del IS TABLE OF VARCHAR2(100); 
l_del t_del; 

CURSOR c IS 
SELECT MIN(ROWID) RID 
    FROM test_tbl TAB 
    GROUP BY TAB.age, TAB.gender 
    HAVING COUNT(*) > 1; 

BEGIN 
    OPEN c; 
    LOOP 
    FETCH c BULK COLLECT INTO l_del; 
    EXIT WHEN l_del.COUNT = 0; 
    FORALL i IN l_del.FIRST..l_del.last 
    DELETE FROM test_tbl WHERE ROWID = l_del(i); 
    END LOOP; 
END; 
0

嘿。根据你的问题,尽管为这个简单的任务创建 过程并不可靠,但这可以通过Pure SQL轻松完成。 但是,如果它的真正意图使它作为一个存储过程,那么我会 建议使用PURE SQL逻辑比使用任何类型的循环,因为 将是上下文切换,这将对数据库产生影响。 下面是我认为有用的一个片段,也纳入了 分析功能,以满足您的问题。让我知道它是否有帮助。

CREATE OR REPLACE PROCEDURE Dup_DELETE 
AS 
BEGIN 
    DELETE 
    FROM EMP 
    WHERE EMP.ROWID IN 
    -- Assuming that i am trying to segregate the duplicate values on Empno and ename 
    (SELECT A.ROWID 
    FROM 
     (SELECT ROW_NUMBER() OVER(PARTITION BY EMPNO,ENAME ORDER BY JOB DESC) RNK, 
     empno, 
     ename, 
     rowid 
     FROM EMP 
    )A 
    WHERE A.RNK <> 1 
    ); 
END; 
1

只要把你的SQL语句的过程。没有规则说你必须改变方法,因为它是PL/SQL。例如,

create or replace procedure dedupe_sometable 
as 
begin 
    delete sometable 
    where rowid in 
      (select lag(rowid) over (partition by id order by null) 
      from sometable); 
end dedupe_sometable; 

根据需要添加日志记录等。

(理想情况下,这将在一个包中,而不是一个独立的程序。)