Oracle
 sql >> Teknologi Basis Data >  >> RDS >> Oracle

bagaimana cara membuat pemicu seperti batasan kunci utama?

Hanya karena Anda tampaknya berniat melihat ini gagal, dan tidak mengambil apa pun dari poin APC, ini tampaknya berfungsi pada pandangan pertama selama itu adalah before pemicu:

create table t42 (id number);

create trigger trig42
before insert or update on t42
for each row
declare
  c number;
begin
  if :new.id is null then
    raise_application_error(-20001, 'ID is null');    
  end if;
  select count(*) into c from t42 where id = :new.id;
  if c > 0 then
    raise_application_error(-20002, 'ID is not unique');
  end if;
end;
/

Ini mengkompilasi dan jika Anda memasukkan data, Anda mendapatkan perilaku yang tampaknya Anda inginkan:

insert into t42 values (1);

1 rows inserted.

insert into t42 values (1);

Error starting at line 20 in command:
insert into t42 values (1)
Error report:
SQL Error: ORA-20002: ID is not unique
ORA-06512: at "STACKOVERFLOW.TRIG42", line 9
ORA-04088: error during execution of trigger 'STACKOVERFLOW.TRIG42'

insert into t42 values (null);

Error starting at line 22 in command:
insert into t42 values (null)
Error report:
SQL Error: ORA-20001: ID is null
ORA-06512: at "STACKOVERFLOW.TRIG42", line 5
ORA-04088: error during execution of trigger 'STACKOVERFLOW.TRIG42'

select * from t42;

        ID
----------
         1 

Yang tampaknya melakukan apa yang Anda inginkan. Tetapi tidak jika Anda memiliki lebih dari satu sesi. Saya belum berkomitmen dalam sesi ini; di sesi lain yang bisa saya lakukan:

insert into t42 values (1);

1 row created.

select * from t42;

        ID
----------
         1

1 row selected.

Hmm, itu aneh. Yah, mungkin itu ditunda... mari kita komit keduanya:

commit;

select * from t42;
        ID
----------
         1
         1

2 rows selected.

Ups. Setelah sesi tidak dapat melihat data yang tidak dikomit dari sesi lain, jadi ini tidak akan pernah berfungsi.

Selain itu, masalah tabel mutasi muncul dengan sendirinya saat kita menyisipkan beberapa baris dalam satu pernyataan:

SQL> insert into t42 select level+1 from dual connect by level <= 5; 
insert into t42 select level+1 from dual connect by level <= 5
            *
ERROR at line 1:
ORA-04091: table STACKOVERFLOW.T42 is mutating, trigger/function may not see it
ORA-06512: at "STACKOVERFLOW.TRIG42", line 7
ORA-04088: error during execution of trigger 'STACKOVERFLOW.TRIG42'


SQL> 

Ups ganda.

Bahkan dengan after pemicu dan paket untuk mengatasi masalah tabel bermutasi, Anda masih memiliki masalah ini (saya pikir), kecuali jika Anda mengunci seluruh tabel untuk setiap sisipan atau pembaruan. Seperti yang dikatakan APC, batasan diterapkan jauh di dalam basis data, bukan pada level ini.

Tidak ketika Anda memiliki lebih dari satu sesi, tidak. Dan bahkan dalam satu sesi, kecuali Anda memiliki indeks pada kolom, kinerja tidak akan diskalakan sebagai count(*) akan semakin lambat. Dan jika Anda memiliki indeks, mengapa tidak menjadikannya sebagai indeks unik?

Terakhir, dari pedoman desain pemicu :



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Alternatif dari sys_refcursor

  2. Klien Oracle ORA-12541:TNS:tidak ada pendengar

  3. Konversi array byte dari Oracle RAW ke System.Guid?

  4. Apakah mungkin menjalankan skrip SQLPLUS pada file yang dikodekan sebagai UTF-8 dengan BOM

  5. Cara menangani/menggunakan karakter khusus seperti persen (%) dan ampersand (&) dalam kueri Oracle SQL