作为标题,我想在Oracle / PLSQL中创建一个过程来删除在某些列中共享相同值的行。我知道如何使用Query实现它,但如何使用过程来实现它?我必须使用任何循环吗?我是PLSQL的新手
请帮忙,非常感谢你!
答案 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;