Bukan praktik yang baik untuk meneruskan nilai untuk IN
kondisi sebagai rangkaian string. Hal pertama, tentu saja, keamanan dan kebenaran, tetapi poin berikutnya adalah kinerja.
Setiap kali Anda memanggil pernyataan, mesin database mem-parsingnya, membuat rencana kueri dan setelah itu melakukan tindakan yang ditentukan dalam pernyataan SQL.
Jika Anda membuat teks kueri dari awal setiap kali, maka ketiga tahap dijalankan setiap kali.
Tetapi jika Anda menggunakan variabel ikat sepanjang waktu, kueri terlihat sama sehingga database menggunakan rencana kueri yang di-cache yang mempercepat eksekusi kueri. Bahkan Anda dapat memanggil oci_parse()
hanya sekali dan gunakan kembali $stmt
variabel dengan set parameter yang disediakan berbeda.
Jadi, untuk kinerja terbaik Anda harus menggunakan variabel bind dan mengisinya dengan array menggunakan oci_bind_array_by_name
.
Hal tambahan adalah bahwa mengambil hasil menggunakan oci_fetch_all
dapat bekerja lebih cepat daripada membaca hasil yang ditetapkan baris demi baris, tetapi itu tergantung pada logika hasil pemrosesan.
Perbarui
Tampaknya melewatkan parameter array hanya berfungsi jika Anda akan menjalankan blok PL/SQL dan tidak dapat menggunakannya dengan pernyataan SQL. Tetapi kemungkinan lain adalah menggunakan koleksi
untuk melewati daftar nilai parameter. Dimungkinkan untuk memenuhi kondisi pertanyaan bahkan dengan array, tetapi cara ini kurang elegan.
Selain cara yang berbeda untuk menanyakan database, ada yang namanya pengaturan sistem. Dalam kasus PHP ada beberapa parameter di php.ini
file yang mengontrol interaksi dengan Oracle. Salah satunya (oci8.statement_cache_size
) terkait dengan cache dan kinerja kueri.
Contoh
Semua contoh menggunakan pengaturan data yang sama di Oracle.
Untuk meneruskan data, saya memilih SYS.ODCIVarchar2List
yang telah ditentukan sebelumnya. jenis, tetapi juga memungkinkan untuk menentukan jenis khusus dengan karakteristik yang sama (ditunjukkan dalam contoh penyiapan data). Di bawah ini adalah kode untuk mendemostrasikan penyiapan skema data dan prinsip penggunaan koleksi di DML.
create table myTable(value varchar2(100), key varchar2(100))
/
insert into myTable(value, key)
select * from (
select 'apple', 'apple_one' from dual union all
select 'apple', 'apple_two' from dual union all
select 'banana', 'banana_one' from dual union all
select 'orange', 'orange_one' from dual union all
select 'orange', 'orange_two' from dual union all
select 'potato', 'potato_one' from dual
)
/
create or replace type TCustomList as table of varchar2(4000)
/
create or replace package TestPackage as
type TKeyList is table of varchar2(1000) index by binary_integer;
function test_select(pKeyList in out TKeyList) return sys_refcursor;
end;
/
create or replace package body TestPackage is
function test_select(pKeyList in out TKeyList) return sys_refcursor
is
vParam sys.ODCIVarchar2List := sys.ODCIVarchar2List();
vCur sys_refcursor;
vIdx binary_integer;
begin
vIdx := pKeyList.first;
while(vIdx is not null) loop
vParam.Extend;
vParam(vParam.last) := pKeyList(vIdx);
vIdx := pKeyList.next(vIdx);
end loop;
open vCur for
select * from myTable where value in (select column_value from table(vParam))
;
return vCur;
end;
end;
/
Kueri untuk mendemonstrasikan koleksi:
--select by value list
select * from myTable
where value in (
select column_value
from table(Sys.ODCIVarchar2List('banana','potato'))
)
/
--same with custom type
select * from myTable
where value in (
select column_value
from table(TCustomList('banana','potato'))
)
/
--same with demonstration of casting
select * from myTable
where value in (
select column_value
from table(cast(TCustomList('banana','potato') as Sys.ODCIVarchar2List))
)
/
Contoh 1 - panggilan dari PHP menggunakan koleksi
<?php
$keyList = array('apple', 'potato');
$conn = oci_pconnect("user_name", "user_password", "SERVER_TNS_NAME");
$stmt = oci_parse($conn, "SELECT * FROM myTable where value in (select column_value from table(:key_list))");
$coll = oci_new_collection($conn, 'ODCIVARCHAR2LIST','SYS');
for ($i=0; $i < count($keyList); $i++) {
$coll->append($keyList[$i]);
}
oci_bind_by_name($stmt, 'key_list', $coll, -1, OCI_B_NTY);
oci_execute($stmt);
while($row = oci_fetch_array($stmt, OCI_ASSOC)) {
echo "{$row['KEY']}, {$row['VALUE']}\n"; // Print the values
}
echo "---\n";
$coll->free();
//-- Run statement another time with different parameters
//-- without reparsing.
$coll = oci_new_collection($conn, 'ODCIVARCHAR2LIST','SYS');
$coll->append('banana');
oci_bind_by_name($stmt, 'key_list', $coll, -1, OCI_B_NTY);
oci_execute($stmt);
while($row = oci_fetch_array($stmt, OCI_ASSOC)) {
echo "{$row['KEY']}, {$row['VALUE']}\n"; // Print the values
}
echo "---\n";
$coll->free();
oci_free_statement($stmt);
oci_close($conn);
?>
Contoh 2 - Panggilan dari PHP menggunakan array dan paket
<?php
$keyList = array('apple', 'potato');
$conn = oci_pconnect("user_name", "user_password", "SERVER_TNS_NAME");
$stmt = oci_parse($conn, "begin :cur := TestPackage.test_select(:key_list); end;");
$curs = oci_new_cursor($conn);
oci_bind_array_by_name($stmt, "key_list", $keyList, 2, 100, SQLT_CHR);
oci_bind_by_name($stmt, "cur", $curs, -1, OCI_B_CURSOR);
oci_execute($stmt);
oci_execute($curs);
while($row = oci_fetch_array($curs, OCI_ASSOC)) {
echo "{$row['KEY']}, {$row['VALUE']}\n"; // Print the values
}
echo "---\n";
//-- Run statement another time with different parameters
//-- without reparsing.
$keyList = array('banana');
oci_bind_array_by_name($stmt, "key_list", $keyList, 2, 100, SQLT_CHR);
oci_execute($stmt);
oci_execute($curs);
while($row = oci_fetch_array($curs, OCI_ASSOC)) {
echo "{$row['KEY']}, {$row['VALUE']}\n"; // Print the values
}
echo "---\n";
oci_free_statement($stmt);
oci_close($conn);
?>
Contoh 3 - panggilan dari PHP menggunakan array dan blok anonim
<?php
$keyList = array('apple', 'potato');
$conn = oci_pconnect("user_name", "user_password", "SERVER_TNS_NAME");
$stmt = oci_parse($conn, "
declare
type TKeyList is table of varchar2(4000) index by binary_integer;
pKeyList TKeyList := :key_list;
vParam sys.ODCIVarchar2List := sys.ODCIVarchar2List();
vIdx binary_integer;
begin
-- Copy PL/SQL array to a type which allowed in SQL context
vIdx := pKeyList.first;
while(vIdx is not null) loop
vParam.Extend;
vParam(vParam.last) := pKeyList(vIdx);
vIdx := pKeyList.next(vIdx);
end loop;
open :cur for select * from myTable where value in (select column_value from table(vParam));
end;
");
$curs = oci_new_cursor($conn);
oci_bind_array_by_name($stmt, "key_list", $keyList, 2, 100, SQLT_CHR);
oci_bind_by_name($stmt, "cur", $curs, -1, OCI_B_CURSOR);
oci_execute($stmt);
oci_execute($curs);
while($row = oci_fetch_array($curs, OCI_ASSOC)) {
echo "{$row['KEY']}, {$row['VALUE']}\n"; // Print the values
}
echo "---\n";
//-- Run statement another time with different parameters
//-- without reparsing.
$keyList = array('banana');
oci_bind_array_by_name($stmt, "key_list", $keyList, 2, 100, SQLT_CHR);
oci_execute($stmt);
oci_execute($curs);
while($row = oci_fetch_array($curs, OCI_ASSOC)) {
echo "{$row['KEY']}, {$row['VALUE']}\n"; // Print the values
}
echo "---\n";
oci_free_statement($stmt);
oci_close($conn);
?>