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

Mengembalikan hasil bahkan untuk elemen dalam daftar IN yang tidak ada di tabel

Dari sisi SQL, Anda dapat menentukan tipe tabel dan menggunakannya untuk bergabung dengan data asli Anda, seperti:

create type my_array_type as table of number
/

create or replace function f42 (in_array my_array_type)
return sys_refcursor as
  rc sys_refcursor;
begin
  open rc for
    select a.column_value as id,
      case when t.id is null then 'missing'
        else 'present' end as status
    from table(in_array) a
    left join t42 t on t.id = a.column_value
    order by id;

  return rc;
end f42;
/

Demo SQL Fiddle dengan fungsi pembungkus sehingga Anda dapat menanyakannya secara langsung, yang memberikan:

        ID STATUS             
---------- --------------------
         1 present              
         2 present              
         3 present              
         4 missing              
         8 missing              
        23 present              

Dari Java Anda dapat menentukan ARRAY berdasarkan tipe tabel, isi dari array Java, dan panggil fungsi secara langsung; variabel pengikatan parameter tunggal Anda adalah ARRAY , dan Anda mendapatkan kembali kumpulan hasil yang dapat Anda ulangi seperti biasa.

Sebagai garis besar dari sisi Java:

int[] ids = { 1, 2, 3, 4, 8, 23 };
ArrayDescriptor aDesc = ArrayDescriptor.createDescriptor("MY_ARRAY_TYPE",
  conn);
oracle.sql.ARRAY ora_ids = new oracle.sql.ARRAY(aDesc, conn, ids);

cStmt = (OracleCallableStatement) conn.prepareCall("{ call ? := f42(?) }");
cStmt.registerOutParameter(1, OracleTypes.CURSOR);
cStmt.setArray(2, ora_ids);
cStmt.execute();
rSet = (OracleResultSet) cStmt.getCursor(1);

while (rSet.next())
{
    System.out.println("id " + rSet.getInt(1) + ": " + rSet.getString(2));
}

Yang memberikan:

id 1: present
id 2: present
id 3: present
id 4: missing
id 8: missing
id 23: present

Seperti yang disebutkan Maheswaran Ravisankar, ini memungkinkan sejumlah elemen untuk dilewati; Anda tidak perlu tahu berapa banyak elemen yang ada pada waktu kompilasi (atau berurusan dengan maksimum teoritis), Anda tidak dibatasi oleh jumlah maksimum ekspresi yang diizinkan dalam IN atau dengan panjang string tunggal yang dibatasi, dan Anda tidak perlu membuat dan menguraikan string untuk meneruskan beberapa nilai.

Seperti yang ditunjukkan oleh ThinkJet, jika Anda tidak ingin membuat tipe tabel Anda sendiri, Anda dapat menggunakan koleksi yang telah ditentukan sebelumnya, yang ditunjukkan di sini; fungsi utama adalah sama selain dari deklarasi parameter:

create or replace function f42 (in_array sys.odcinumberlist)
return sys_refcursor as
...    

Fungsi pembungkus mengisi array sedikit berbeda, tetapi di sisi Java Anda hanya perlu mengubah baris ini:

ArrayDescriptor aDesc =
  ArrayDescriptor.createDescriptor("SYS.ODCINUMBERLIST", conn );

Menggunakan ini juga berarti (seperti yang juga ditunjukkan oleh ThinkJet!) bahwa Anda dapat menjalankan kueri asli yang berdiri sendiri tanpa mendefinisikan fungsi:

select a.column_value as id,
case when t.id is null then 'missing'
else 'present' end as status
from table(sys.odcinumberlist(1, 2, 3, 4, 8, 23)) a
left join t42 t on t.id = a.column_value
order by id;

(SQL Fiddle).

Dan itu berarti Anda dapat memanggil kueri langsung dari Java:

int[] ids = { 1, 2, 3, 4, 8, 23 };
ArrayDescriptor aDesc = ArrayDescriptor.createDescriptor("SYS.ODCINUMBERLIST", conn );
oracle.sql.ARRAY ora_ids = new oracle.sql.ARRAY(aDesc, conn, ids);

sql = "select a.column_value as id, "
    + "case when t.id is null then 'missing' "
    + "else 'present' end as status "
    + "from table(?) a "
    + "left join t42 t on t.id = a.column_value "
    + "order by id";
pStmt = (OraclePreparedStatement) conn.prepareStatement(sql);
pStmt.setArray(1, ora_ids);
rSet = (OracleResultSet) pStmt.executeQuery();

while (rSet.next())
{
    System.out.println("id " + rSet.getInt(1) + ": " + rSet.getString(2));
}

... yang mungkin Anda sukai.

Ada ODCIVARCHAR2LIST yang telah ditentukan sebelumnya ketik juga, jika Anda benar-benar melewatkan string - kode asli Anda tampaknya berfungsi dengan string meskipun berisi angka, jadi tidak yakin mana yang benar-benar Anda butuhkan.

Karena tipe ini didefinisikan sebagai VARRAY(32767) Anda dibatasi hingga 32k nilai, sementara mendefinisikan tabel Anda sendiri menghilangkan batasan itu; tapi jelas itu hanya penting jika Anda melewati banyak nilai.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. 12.2 Fitur Baru RAC/GI

  2. C#:Berikan tipe yang ditentukan pengguna ke prosedur tersimpan Oracle

  3. Hasilkan data uji menggunakan pengembang Oracle PL/SQL

  4. Pertanyaan ReadyStatement di Jawa melawan Oracle

  5. ORA-06502:PL/SQL:kesalahan numerik atau nilai:buffer string karakter terlalu kecil