使用Oracle / PLSQL

时间:2016-01-05 03:27:54

标签: oracle plsql procedure

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

请帮忙,非常感谢你!

5 个答案:

答案 0 :(得分: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列中具有相同值的行。

答案 1 :(得分:1)

  

嘿。根据你的问题,尽管创建它是不可取的   这个简单任务的过程可以通过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;

答案 2 :(得分: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;

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

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

答案 3 :(得分:0)

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

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

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

答案 4 :(得分: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;