Việc chuyển các giá trị cho IN
không phải là một phương pháp hay điều kiện như nối chuỗi. Tất nhiên, điều đầu tiên là bảo mật và tính đúng đắn, nhưng điểm tiếp theo là hiệu suất.
Mỗi lần bạn gọi công cụ cơ sở dữ liệu câu lệnh sẽ phân tích cú pháp nó, hãy xây dựng một kế hoạch truy vấn và sau đó thực hiện các hành động được chỉ định trong câu lệnh SQL.
Nếu bạn xây dựng văn bản truy vấn từ đầu mỗi lần, sau đó tất cả ba giai đoạn được thực thi mỗi lần.
Nhưng nếu bạn sử dụng các biến liên kết mọi lúc, truy vấn trông giống nhau, vì vậy cơ sở dữ liệu sử dụng kế hoạch truy vấn được lưu trong bộ nhớ cache để tăng tốc độ thực thi truy vấn. Thậm chí bạn có thể gọi oci_parse ()
chỉ một lần và sử dụng lại $ stmt
biến có tập hợp các tham số được cung cấp khác nhau.
Vì vậy, để có hiệu suất tốt nhất, bạn phải sử dụng biến bind và điền nó vào mảng bằng cách sử dụng oci_bind_array_by_name
.
Điều bổ sung là truy xuất kết quả bằng cách sử dụng oci_fetch_all
có thể hoạt động nhanh hơn việc đọc kết quả được đặt từng hàng một, nhưng nó phụ thuộc vào logic của kết quả xử lý.
Cập nhật
Có vẻ như việc truyền các tham số mảng chỉ hoạt động nếu bạn thực thi khối PL / SQL và không thể sử dụng nó với các câu lệnh SQL. Nhưng một khả năng khác là sử dụng các bộ sưu tập
để chuyển danh sách các giá trị tham số. Có thể thỏa mãn các điều kiện của câu hỏi ngay cả với các mảng, nhưng cách này kém thanh lịch hơn.
Bên cạnh một số cách khác để truy vấn cơ sở dữ liệu, còn có những thứ như cài đặt hệ thống. Trong trường hợp PHP, có một số tham số trong php.ini
tệp kiểm soát tương tác với Oracle. Một trong số chúng ( oci8.statement_cache_size
) liên quan đến hiệu suất và bộ đệm ẩn truy vấn.
Ví dụ
Tất cả các ví dụ đều sử dụng cùng một thiết lập dữ liệu trong Oracle.
Để chuyển dữ liệu, tôi chọn SYS.ODCIVarchar2List
được xác định trước. nhưng cũng có thể xác định kiểu tùy chỉnh với các đặc điểm giống nhau (được trình bày trong ví dụ thiết lập dữ liệu). Dưới đây là mã để phân tích thiết lập lược đồ dữ liệu và nguyên tắc sử dụng tập hợp trong 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;
/
Truy vấn để chứng minh bộ sưu tập:
--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))
)
/
Ví dụ 1 - gọi từ PHP bằng cách sử dụng bộ sưu tập
<?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);
?>
Ví dụ 2 - Gọi từ PHP bằng cách sử dụng mảng và gói
<?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);
?>
Ví dụ 3 - gọi từ PHP bằng cách sử dụng mảng và khối ẩn danh
<?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);
?>