作为标题,我想在Oracle/PLSQL中创建一个过程来删除在某些列中共享相同值的行。我知道如何使用查询来实现它,但是如何使用过程来实现它?我必须使用任何循环吗?我很新PLSQL使用Oracle/PLSQL中的过程删除重复记录
请大家帮忙,多谢!
作为标题,我想在Oracle/PLSQL中创建一个过程来删除在某些列中共享相同值的行。我知道如何使用查询来实现它,但是如何使用过程来实现它?我必须使用任何循环吗?我很新PLSQL使用Oracle/PLSQL中的过程删除重复记录
请大家帮忙,多谢!
如果你想要一个简单的过程,从一个特定的表中删除,你可以使用下面的代码:
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中具有相同值的行。
如果你知道如何在SQL中完成它,最好在SQL中完成它。只有当您不能在SQL语句中编写特定任务时,或者在查询中存在性能问题,并且可以通过在PL/SQL中编写逻辑来改进(第二种情况非常罕见)时,才应使用PL/SQL。
如果要编写PL/SQL过程来进行参数化,以便可以传递任何表以删除重复项,那么这很有意义。您需要在过程中动态生成删除语句并使用execute immediate
执行。
如果你的目的是学习PL/SQL,那么它就是编程语言,你需要花一些时间,就好像你在学习新的编程语言一样。
不是一个真正的答案。应该是一个评论。 – Drumbeg
不建议将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;
嘿。根据你的问题,尽管为这个简单的任务创建 过程并不可靠,但这可以通过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;
只要把你的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;
根据需要添加日志记录等。
(理想情况下,这将在一个包中,而不是一个独立的程序。)
非常感谢! –