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

Bagaimana menerapkan urutan multidimensi

Satu-satunya cara untuk melakukannya adalah dengan tabel kontrol kode ...

create table code_control
    (year number(4,0) not null
     , type varchar2(1) not null
     , last_number number(38,0) default 1 not null
     , primary key (year,type)
    )
organization index
/   

... yang dipertahankan seperti ini ...

create or replace function get_next_number
    (p_year in number, p_type in varchar2)
    return number
is
    pragma autonomous_transaction;
    cursor cur_cc is
        select last_number + 1
        from code_control cc
        where cc.year= p_year
        and cc.type = p_type
        for update of last_number;
    next_number number;
begin
    open cur_cc;
    fetch cur_cc into next_number;
    if cur_cc%found then
        update code_control
        set last_number = next_number
        where current of cur_cc;
    else
        insert into code_control (year,type)
        values (p_year, p_type)
        returning last_number into next_number;
    end if;    
    commit;
    return next_number;
end;
/

Yang penting PILIH...UNTUK UPDATE. Penguncian pesimistis menjamin keunikan dalam lingkungan multi-pengguna. PRAGMA memastikan bahwa pemeliharaan code_control tidak mencemari transaksi yang lebih luas. Ini memungkinkan kita untuk memanggil fungsi dalam pemicu tanpa kebuntuan.

Berikut adalah tabel dengan kunci seperti milik Anda:

create table t42
     (year number(4,0) not null
     , type varchar2(1) not null
     , id number(38,0) 
     , primary key (year,type, id)
)
/
create or replace trigger t42_trg
    before insert on t42 for each row
begin
    :new.id := get_next_number(:new.year, :new.type);
end;
/

Tidak ada apa-apa sebelum saya mengisi t42 :

SQL> select * from code_control;

no rows selected

SQL> select * from t42;

no rows selected

SQL> insert into t42 (year, type) values (2016, 'A');

1 row created.

SQL> insert into t42 (year, type) values (2016, 'A');

1 row created.

SQL> insert into t42 (year, type) values (2016, 'A');

1 row created.

SQL> insert into t42 (year, type) values (2016, 'B');

1 row created.

SQL> insert into t42 (year, type) values (2016, 'A');

1 row created.

SQL> insert into t42 (year, type) values (2017, 'A');

1 row created.

SQL> select * from t42;

      YEAR T         ID
---------- - ----------
      2016 A          1
      2016 A          2
      2016 A          3
      2016 A          4
      2016 B          1
      2017 A          1

6 rows selected.

SQL> select * from code_control;

      YEAR T LAST_NUMBER
---------- - -----------
      2016 A           4
      2016 B           1
      2017 A           1

SQL> 

Jadi keberatan yang jelas untuk implementasi ini adalah skalabilitas. Memasukkan transaksi diserialkan pada code_control meja. Itu benar sekali. Namun kunci ditahan untuk waktu sesingkat mungkin, jadi ini seharusnya tidak menjadi masalah meskipun t42 tabel diisi berkali-kali dalam satu detik.

Namun, jika tabel mengalami sejumlah besar sisipan bersamaan, penguncian dapat menjadi masalah. Sangat penting bahwa meja memiliki slot Transaksi Tertarik yang cukup (INITRANS, MAXTRANS) untuk mengatasi permintaan bersamaan. Tetapi sistem yang sangat sibuk mungkin memerlukan implementasi yang lebih cerdas (mungkin menghasilkan ID dalam batch); jika tidak, abaikan kunci majemuk demi urutan (karena urutan melakukan skala di lingkungan multi-pengguna).




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Oracle SQL:Memfilter oleh ROWNUM tidak mengembalikan hasil ketika seharusnya

  2. ORA-00907 saat mencoba membuat batasan CHECK

  3. Permintaan Oracle SQL - menghasilkan catatan antara dua tanggal

  4. Kenapa sqlplus tidak terhubung?

  5. Contoh untuk Mendemonstrasikan Kerentanan SQL Injection dan Pencegahannya di Oracle