Es empfiehlt sich nicht, Werte für IN
zu übergeben Bedingung als Stringverkettung. Das Wichtigste natürlich, Sicherheit und Korrektheit, aber der nächste Punkt ist die Leistung.
Jedes Mal, wenn Sie die Anweisung aufrufen, analysiert die Datenbank-Engine sie, erstellt einen Abfrageplan und führt danach die in der SQL-Anweisung angegebenen Aktionen aus.
Wenn Sie erstellen den Abfragetext jedes Mal von Grund auf neu und dann werden alle drei Phasen jedes Mal ausgeführt.
Aber wenn Sie Bind-Variablen verwenden, sieht die Abfrage immer gleich aus, sodass die Datenbank einen zwischengespeicherten Abfrageplan verwendet, was die Abfrageausführung beschleunigt. Sogar Sie können oci_parse()
aufrufen nur einmal und verwenden Sie $stmt
wieder Variable mit einem anderen Satz von bereitgestellten Parametern.
Für die beste Leistung müssen Sie also eine Bind-Variable verwenden und sie mit einem Array füllen, indem Sie oci_bind_array_by_name
.
Außerdem können Ergebnisse mit oci_fetch_all
ist möglicherweise schneller als das zeilenweise Lesen der Ergebnismenge, hängt jedoch von der Logik der Verarbeitung der Ergebnisse ab.
Aktualisieren
Scheint, dass das Übergeben von Array-Parametern nur funktioniert, wenn Sie einen PL/SQL-Block ausführen und ihn nicht mit SQL-Anweisungen verwenden können. Aber eine andere Möglichkeit ist die Verwendung von Sammlungen
um eine Liste von Parameterwerten zu übergeben. Es ist möglich, Bedingungen der Frage auch mit Arrays zu erfüllen, aber dieser Weg ist weniger elegant.
Neben verschiedenen Möglichkeiten, eine Datenbank abzufragen, gibt es so etwas wie Systemeinstellungen. Im Fall von PHP gibt es einige Parameter in php.ini
Datei, die die Interaktion mit Oracle steuert. Einer davon (oci8.statement_cache_size
) im Zusammenhang mit dem Zwischenspeichern und der Leistung einer Abfrage.
Beispiele
Alle Beispiele verwenden die gleiche Dateneinstellung in Oracle.
Um Daten zu übergeben, wähle ich die vordefinierte SYS.ODCIVarchar2List
Typ, aber es ist auch möglich, einen benutzerdefinierten Typ mit denselben Merkmalen zu definieren (im Beispiel für die Dateneinrichtung demonstriert). Unten finden Sie Code zur Demonstration der Einrichtung des Datenschemas und des Prinzips der Verwendung von Sammlungen in 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;
/
Abfragen zum Demonstrieren von Sammlungen:
--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))
)
/
Beispiel 1 – Aufruf von PHP mit Sammlungen
<?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);
?>
Beispiel 2 – Aufruf von PHP mit Array und 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);
?>
Beispiel 3 – Aufruf von PHP mit Array und anonymem Block
<?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);
?>