MySQL Limit Funktion mit Oracle und PHP für jqGrid


Für ein Projekt habe ich gerade mit dem tollen jqgrid-Plugin für jQuery gearbeitet. Damit lassen sich recht schnell und einfach Tabellendaten dynamisch darstellen. Das Plugin ist sehr gut dokumentiert und es gibt viele Beispiele. Diese beziehen sich aber i.d.R. auf MySQL. Nun habe ich hier aber eine Oracle Datenbank aus der ich die Daten beziehe.

jqGrid zeigt die Daten standardmässig „gepaged“ an, d.h. nur eine bestimmte Anzahl Datensätze pro Seite. Diese werden dynamisch via Ajax-Request neu gelesen. Da wir aber selbstverständlich nicht immer alle Sätze aus der Datenbank lesen wollen und anschliessend filtern, soll das Query nur die nötigen Sätze zurückliefern.

In MySQL ist das einfach mit der Limit-Funktion möglich. Diese Funktion gibt es so leider in Oracle nicht, weshalb man etwas umständlicher zum Ziel kommen muss. Dazu umfassen wir uns eigentlichs SQL (hier ###select###) zusätzlich.

SELECT   *   FROM
(
SELECT
r.*, ROWNUM as row_number
FROM
( ###select### ORDER BY ###sidx### ###sord###) r
WHERE
ROWNUM <= :end_row
)
WHERE :start_row <= row_number

Da ich meine SQL in diesem Projekt als TXT-Datei einlese habe ich hier 3 Marker die ich anschliessend mit den entsprechenden Werten ersetze um mein tatsächliches Statement zu bekommen.

$sql = file_get_contents(‚modules/reports/sql/oracle_limit-wrap.sql‘);
$sql = str_replace(‚###select###‘,$select,$sql);
$sql = str_replace(‚###sidx###‘,$sidx,$sql);
$sql = str_replace(‚###sord###‘,$sord,$sql);

###select### / $select ist das SQL mit dem ich die eigentlich gewollten Daten aus der Datenbank ziehe.
###sidx### und ###sord### sind die Parameter die von jqGrid beim Update der Ansicht übergeben werden (Sort-Index und Sort-Order).

Bevor wir nun unser neues SQL abschicken müssen wir noch :start_row und :end_row ermitteln. Diese sind abhängig von den von jqGrid übergebenen Parametern ($limit und $start). Sie kommen aus der Berechnung der Gesamtsätze wie es im jqGrid-Beispiel zu sehen ist. $count ist hierbei die Gesamtzahl aller Sätze die wir via „select count(*) …“ ermittelt haben.

if( $count > 0 ) {
$total_pages = ceil($count/$limit);
} else {
$total_pages = 0;
}

if ($page > $total_pages) $page=$total_pages;
$start = $limit*$page – $limit+1;
$end = $start + $limit-1;
if($start <0) $start = 0;

Nun aber endlich das Query ausführen:

$stmt = oci_parse($conn,$sql);
oci_bind_by_name($stmt, ‚:start_row‘, $start);
oci_bind_by_name($stmt, ‚:end_row‘, $end);    
oci_execute($stmt);
$rows_per_page = $limit;    
ocisetprefetch($stmt, $rows_per_page);

// build result-array
while ($row = oci_fetch_array($stmt, OCI_ASSOC+OCI_RETURN_NULLS)) {
$rows[] = $row;                  
}

Zu beachten ist noch, dass wir in unserem Result-Array pro Datensatz jetzt noch eine zusätzliches Feld ROW_NUM haben, das wir in PHP oder im jqGrid noch rausfiltern können.

Zusammenfassung in einfachen Worten:
Anstelle der LIMIT-Funktion umfassen wir unser SELECT nochmals mit einem zusätzlichen SQL und übergeben diese die Limit-Parameter.

OFFTOPIC: Wie bringe ich WordPress bei Quellcode schön darzustellen?

,