Saya biasanya hanya memasukkan dan menjebak pengecualian DUP_VAL_ON_INDEX, karena ini adalah kode yang paling sederhana. Ini lebih efisien daripada memeriksa keberadaan sebelum memasukkan. Saya tidak menganggap melakukan ini sebagai "bau busuk" (frasa mengerikan!) karena pengecualian yang kami tangani diajukan oleh Oracle - ini tidak seperti menaikkan pengecualian Anda sendiri sebagai mekanisme kontrol aliran.
Berkat komentar Igor, saya sekarang telah menjalankan dua tolok ukur berbeda tentang ini:(1) di mana semua upaya penyisipan kecuali yang pertama adalah duplikat, (2) di mana semua sisipan bukan duplikat. Realitas akan terletak di suatu tempat di antara dua kasus.
Catatan:pengujian dilakukan pada Oracle 10.2.0.3.0.
Kasus 1:Sebagian besar duplikat
Tampaknya pendekatan yang paling efisien (dengan faktor signifikan) adalah memeriksa keberadaan SAAT memasukkan:
prompt 1) Check DUP_VAL_ON_INDEX
begin
for i in 1..1000 loop
begin
insert into hasviewed values(7782,20);
exception
when dup_val_on_index then
null;
end;
end loop
rollback;
end;
/
prompt 2) Test if row exists before inserting
declare
dummy integer;
begin
for i in 1..1000 loop
select count(*) into dummy
from hasviewed
where objectid=7782 and userid=20;
if dummy = 0 then
insert into hasviewed values(7782,20);
end if;
end loop;
rollback;
end;
/
prompt 3) Test if row exists while inserting
begin
for i in 1..1000 loop
insert into hasviewed
select 7782,20 from dual
where not exists (select null
from hasviewed
where objectid=7782 and userid=20);
end loop;
rollback;
end;
/
Hasil (setelah dijalankan sekali untuk menghindari overhead parsing):
1) Check DUP_VAL_ON_INDEX
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.54
2) Test if row exists before inserting
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.59
3) Test if row exists while inserting
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.20
Kasus 2:tidak ada duplikat
prompt 1) Check DUP_VAL_ON_INDEX
begin
for i in 1..1000 loop
begin
insert into hasviewed values(7782,i);
exception
when dup_val_on_index then
null;
end;
end loop
rollback;
end;
/
prompt 2) Test if row exists before inserting
declare
dummy integer;
begin
for i in 1..1000 loop
select count(*) into dummy
from hasviewed
where objectid=7782 and userid=i;
if dummy = 0 then
insert into hasviewed values(7782,i);
end if;
end loop;
rollback;
end;
/
prompt 3) Test if row exists while inserting
begin
for i in 1..1000 loop
insert into hasviewed
select 7782,i from dual
where not exists (select null
from hasviewed
where objectid=7782 and userid=i);
end loop;
rollback;
end;
/
Hasil:
1) Check DUP_VAL_ON_INDEX
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.15
2) Test if row exists before inserting
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.76
3) Test if row exists while inserting
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.71
Dalam hal ini DUP_VAL_ON_INDEX menang sejauh satu mil. Perhatikan bahwa "pilih sebelum menyisipkan" adalah yang paling lambat dalam kedua kasus.
Jadi tampaknya Anda harus memilih opsi 1 atau 3 sesuai dengan kemungkinan relatif sisipan adalah duplikat atau bukan.