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

Dapatkan detail Akun di Oracle menggunakan fungsi

Anda tampaknya sedikit kacau dalam deskripsi masalah, harap format pertanyaan Anda dan buat lebih mudah dibaca. Pokoknya solusinya sederhana. Anda hanya perlu satu if pernyataan, di mana, tergantung pada level, Anda mencari di tabel pertama atau kedua dan kolom yang tepat:

create or replace function get_accountdetails (par_input in varchar2) return varchar2 is
  v_aid varchar2(10);
  v_db  varchar2(10);
  v_lvl varchar2(10);
  v_ret varchar2(20) := '';
begin
  v_aid := regexp_substr(par_input, '\d+', 1, 1);
  v_db  := regexp_substr(par_input, '\d+', 1, 2);
  v_lvl := regexp_substr(par_input, '\d+', 1, 3);

  if v_lvl = 1 then
     select dim_cust_key
       into v_ret
       from dim_cust_acnt
       where level1_account_id = v_aid and database_id = v_db;
  elsif v_lvl = 2 then
     select dim_cust_key
       into v_ret
       from dim_cust_dept
       where level2_account_id = v_aid and database_id = v_db;
  else
     select dim_cust_key
       into v_ret
       from dim_cust_dept
       where level3_account_id = v_aid and database_id = v_db;
  end if;
  return v_ret;
end;

Berikut adalah tabel dan contoh pemanggilan fungsi:

create table dim_cust_acnt (dim_cust_key, level1_account_id, database_id) as (
    select 1123, 112, 22 from dual union all
    select 1234, 113, 23 from dual );

create table dim_cust_dept (dim_cust_key, level2_account_id, level3_account_id, database_id) as (
    select 1587, 245, 301, 21 from dual union all
    select 1576, 289, 304, 20 from dual);

select get_accountdetails('[112].[22].[1]') from dual;     -- result: 1123
select get_accountdetails('[289].[20].[2]') from dual;     -- result: 1576
select get_accountdetails('[301].[21].[3]') from dual;     -- result: 1587

Harap gunakan nama kolom yang tepat yang Anda miliki dalam data asli Anda, dan sesuaikan jenis dan panjang variabel jika diperlukan. Saya pikir Anda juga dapat menggunakan satu kueri yang digabungkan, tidak diperlukan fungsi khusus, seperti di bawah ini. Saya menggunakan full join , karena contoh Anda tidak berisi baris yang cocok. Mungkin sederhana join akan cukup.

with t(par_input) as (select '[112].[22].[1]' from dual)
select dim_cust_key
  from dim_cust_acnt a
  full join dim_cust_dept d using (dim_cust_key) 
  cross join t
  where ( 1 = regexp_substr(par_input, '\d+', 1, 3)  
          and regexp_substr(par_input, '\d+', 1, 1) = level1_account_id 
          and regexp_substr(par_input, '\d+', 1, 2) = a.database_id )
     or ( 2 = regexp_substr(par_input, '\d+', 1, 3)  
          and regexp_substr(par_input, '\d+', 1, 1) = level2_account_id 
          and regexp_substr(par_input, '\d+', 1, 2) = d.database_id )
     or ( 3 = regexp_substr(par_input, '\d+', 1, 3)  
          and regexp_substr(par_input, '\d+', 1, 1) = level3_account_id 
          and regexp_substr(par_input, '\d+', 1, 2) = d.database_id )

Hasil:

DIM_CUST_KEY
------------
        1123

Jika Anda menghapus with dan cross join bagian dan tambahkan into klausa maka Anda dapat menggunakan kueri ini dalam fungsi alih-alih if pernyataan.

Sunting:

Maaf atas keterlambatan, saya tidak melihat Stack Overflow akhir-akhir ini. Berikut adalah dua contoh cara menulis fungsi Anda:

Fungsi ini mengembalikan string gabungan:

select get_details_1('[112].[22].[1],[289].[20].[2],[301].[21].[3]') as list from dual;

LIST
------------------
1123,1576,1587

Dan fungsi kedua disalurkan dan mengembalikan data sebagai kumpulan string yang telah ditentukan sebelumnya, sehingga nilai berada dalam baris terpisah.

select column_value 
  from table(get_details_2('[112].[22].[1],[289].[20].[2],[301].[21].[3]'));

COLUMN_VALUE
------------
        1123
        1576
        1587

Anda juga dapat mengurai semua data input terlebih dahulu, menyimpannya di beberapa koleksi, lalu menggunakan pengumpulan massal dalam satu kueri. Ada banyak solusi dan kemungkinan, secara pribadi saya akan menggunakan fungsi pipelined, tetapi itu tergantung pada bentuk output apa yang Anda butuhkan (kumpulan atau string gabungan). Anda juga dapat menambahkan begin ... end blokir dan tangani pengecualian when no_data_found . Anda dapat menyajikan info khusus saat itu atau menghentikan eksekusi, itu tergantung pada perilaku apa yang diharapkan dalam situasi seperti itu.

Fungsi 1:

create or replace function get_details_1 (par_input in varchar2) return varchar2 is
    v_aid varchar2(10);
    v_db  varchar2(10);
    v_lvl varchar2(10);
    v_ret varchar2(20);
    v_all varchar2(200) := '';

    i_cnt int := 0;
begin
    loop
        v_aid := regexp_substr(par_input, '\d+', 1, i_cnt + 1);
        v_db  := regexp_substr(par_input, '\d+', 1, i_cnt + 2);
        v_lvl := regexp_substr(par_input, '\d+', 1, i_cnt + 3);
        i_cnt := i_cnt + 3;
    exit when v_aid is null;
        select dim_cust_key
          into v_ret
          from dim_cust_acnt a
          full join dim_cust_dept d using (dim_cust_key)
          where (v_lvl = 1 and level1_account_id = v_aid and a.database_id = v_db)
             or (v_lvl = 2 and level2_account_id = v_aid and d.database_id = v_db)
             or (v_lvl = 3 and level3_account_id = v_aid and d.database_id = v_db);
       v_all := v_all||','||v_ret;
  end loop;
  return ltrim(v_all, ',');
end;

Fungsi 2:

create or replace function get_details_2 (par_input in varchar2) 
    return sys.odcinumberlist pipelined is

    v_aid varchar2(10);
    v_db  varchar2(10);
    v_lvl varchar2(10);
    v_ret varchar2(20);
    i_cnt int := 0;
begin
    loop
        v_aid := regexp_substr(par_input, '\d+', 1, i_cnt + 1);
        v_db  := regexp_substr(par_input, '\d+', 1, i_cnt + 2);
        v_lvl := regexp_substr(par_input, '\d+', 1, i_cnt + 3);
        i_cnt := i_cnt + 3;
    exit when v_aid is null;
        select dim_cust_key
          into v_ret
          from dim_cust_acnt a
          full join dim_cust_dept d using (dim_cust_key)
          where (v_lvl = 1 and level1_account_id = v_aid and a.database_id = v_db)
             or (v_lvl = 2 and level2_account_id = v_aid and d.database_id = v_db)
             or (v_lvl = 3 and level3_account_id = v_aid and d.database_id = v_db);
       pipe row (v_ret);
  end loop;
  return;
end;



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. ORA-01403 tidak ada data yang ditemukan kesalahan

  2. Adaptor Jaringan tidak dapat membuat koneksi saat terhubung dengan Oracle DB

  3. Perbandingan DATE Oracle SQL mengembalikan hasil yang salah

  4. Bagaimana cara menggabungkan tanpa menggunakan `GROUP BY`?

  5. ROWIDTONCHAR() Fungsi di Oracle