Если выбор из таблицы занимает много времени, я думаю, вы не хотите перехватывать дубликаты, поскольку они происходят, потому что каждая вставка / обновление будет снижать производительность даже больше, чем сейчас.
Следовательно, если таблица не используется 24/7, возможно, вы могли бы график , чтобы проверить и либо уведомить кого-либо, либо, что еще лучше, немедленно принять меры.
Это будет хранимая процедура, например,
create or replace procedure p_del_dup as
begin
delete from your_table a
where a.rowid > (select min(b.rowid)
from your_table b
where b.future_unique_column = a.future_unique_column
);
end;
Пример в реальном времени на основе образца схемы Скотта. Я создам таблицу, содержащую EMP
данные, введу несколько дубликатов и удалим их.
SQL> create table test as select * from emp where deptno in (10, 20);
Table created.
SQL> create or replace procedure p_del_dup as
2 begin
3 delete from test a
4 where a.rowid > (select min(b.rowid)
5 from test b
6 where b.empno = a.empno --> column(s) which will enforce uniqueness
7 );
8 end;
9 /
Procedure created.
Создайте задание базы данных; запланируйте запуск на 02:00 каждую ночь
SQL> declare
2 x number;
3 begin
4 dbms_job.submit
5 ( job => x
6 ,what => 'p_del_dup;'
7 ,next_date => to_date('07.04.2020 02:00:00','dd/mm/yyyy hh24:mi:ss')
8 ,interval => 'TRUNC (SYSDATE+1) + 2 / 24'
9 ,no_parse => false
10 );
11 dbms_output.put_line('Job Number is: ' || to_char(x));
12 commit;
13 end;
14 /
Job Number is: 104
PL/SQL procedure successfully completed.
ОК, теперь давайте вставим несколько дубликатов (все с deptno = 10
):
SQL> insert into test select * from emp where deptno = 10;
3 rows created.
SQL> select * from test order by deptno, ename;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- -------- ---------- ---------- ----------
7782 CLARK MANAGER 7839 09.06.81 2450 10
7782 CLARK MANAGER 7839 09.06.81 2450 10
7839 KING PRESIDENT 17.11.81 5000 10
7839 KING PRESIDENT 17.11.81 5000 10
7934 MILLER CLERK 7782 23.01.82 1300 10
7934 MILLER CLERK 7782 23.01.82 1300 10
7876 ADAMS CLERK 7788 12.01.83 1100 20
7902 FORD ANALYST 7566 03.12.81 3000 20
7566 JONES MANAGER 7839 02.04.81 2975 20
7788 SCOTT ANALYST 7566 09.12.82 3000 20
7369 SMITH CLERK 7902 17.12.80 800 20
11 rows selected.
Я не буду ждать до 02 : 00, поэтому я буду запускать работу вручную. Помните, что его идентификатор равен 104?
SQL> exec dbms_job.run(104);
PL/SQL procedure successfully completed.
SQL> select * from test order by deptno, ename;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- -------- ---------- ---------- ----------
7782 CLARK MANAGER 7839 09.06.81 2450 10
7839 KING PRESIDENT 17.11.81 5000 10
7934 MILLER CLERK 7782 23.01.82 1300 10
7876 ADAMS CLERK 7788 12.01.83 1100 20
7902 FORD ANALYST 7566 03.12.81 3000 20
7566 JONES MANAGER 7839 02.04.81 2975 20
7788 SCOTT ANALYST 7566 09.12.82 3000 20
7369 SMITH CLERK 7902 17.12.80 800 20
8 rows selected.
SQL>
ОК, дубликаты * молча удалены.
При желании вы можете изменить процедуру и - с помощью пакета UTL_MAIL
- отправить кому-нибудь сообщение электронной почты. Если количество удаленных строк достаточно, вы отправите SQL%ROWCOUNT
номер. Или отправьте все, что вы хотите.