phpbar.de logo

Mailinglisten-Archive

[php] SQL-Query zerlegen

[php] SQL-Query zerlegen

Yannik Hampe yannikh at gmail.com
Die Okt 17 21:03:34 CEST 2006



Matthias Spork wrote:
> Hallo,
> 
> gerne würde ich hier nochmal meine Frage aufwerfen, sie aber etwas 
> anders Formulieren:
> 
> Ich suche ein Möglichkeit, mit der ich in ein beliebiges SQL-QUERY 
> (welches auch Subselects enthält) weitere WHERE-Statements einfügen 
> kann. Es würde mir schon reichen zu wissen, wie ich das _eigentliche_ 
> WHERE in dem Query finden kann, falls eines vorhanden ist.
> Hat jemand sowas schonmal gemacht?
Sowas gemacht habe ich noch nie, aber SQL parsen hmm...
WHERE beginnt ja schonmal logischerweise nach dem Schlüsselwort WHERE.
Dann kommt ein boolischer Wert und dann ist die Wherebedingung zu
Ende... Das problematischste dürfte es sein die Länge der WHERE
Bedingung rauszufinden... Entweder du parst den String nach dem where
richtig... Also mit anderen Worten gehst zeichenweise durch, zählst,
wieviele Klammern geöffnet und geschlossen wurden usw. oder du überlegst
dir einfach, womit eine WHERE-Anweisung abgeschlossen werden kann...:
Aus der MySQL-Referenz. Je nach SQL-Server musst du das noch anpassen:

SELECT
    [ALL | DISTINCT | DISTINCTROW ]
      [HIGH_PRIORITY]
      [STRAIGHT_JOIN]
      [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
      [SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]
    select_expr, ...
    [FROM table_references
    [WHERE where_condition]
    [GROUP BY {col_name | expr | position}
      [ASC | DESC], ... [WITH ROLLUP]]
    [HAVING where_condition]
    [ORDER BY {col_name | expr | position}
      [ASC | DESC], ...]
    [LIMIT {[offset,] row_count | row_count OFFSET offset}]
    [PROCEDURE procedure_name(argument_list)]
    [INTO OUTFILE 'file_name' export_options
      | INTO DUMPFILE 'file_name'
      | INTO @var_name [, @var_name]]
    [FOR UPDATE | LOCK IN SHARE MODE]]

Wenn ein WHERE vokommt, dann kommt danach also ein GROUP BY, ein HAVING,
ein ORDER BY, ein LIMIT,..., oder ein Zeilenende.
Du kannst also einfach mit strpos probieren, ob ein ORDER BY, dann ein
HAVING usw. nach dem WHERE vorkommt und dann dir eben einen substring
mit diesem Ende zu kopieren.
Ein Prolem bleibt dabei:
SELECT blabla WHERE somefield='LIMIT'
und du hast ein Problem. Du musst in diesem Fall also auch noch prüfen,
ob nicht schon in Anführungszeichen vorher ein Befehl kommt. Der muss
natürlich nicht alleineig in den Anführungszeichen vorkommen, sondern
auch sowas wie 'aaLIMITbb' kann vorkommen, also nicht einfach.

Da musst du dir dann überlegen ob so eine Trickserei wirklich einfacher
ist als Zeichenweise durchzugehen...
$tmp ='';
$inQuotes =false;
$klammerlevel =0;
for (zeichenweise durchgehen)
{
  //$c enthält das aktuelle Zeichen
  if ($c =="'") $inQuotes =!$inQuotes;
  elseif ($c =='(') ++$klammerlevel;
  elseif ($c ==')') --$klammerlevel;
  else $tmp .=$c;
  if ($tmp endet mit einem der oben genannten schlüsselwörtern hinter WHERE)
  {
    //gefundenes Schlüsselwort entfernen und schon hast du den
WHERE-string in $tmp
  }
}
Das habe ich jetzt allerdings mal so ganz easy im Kopf direkt in
Thunderbird gehackt und ich versuche niemanden zu erzählen, dass diese
Funktion vollständig ist. Aber es sollte genug Denkansatz sein um dir
bei deinem problem weiter zu helfen...
> 
> Viele Grüße
> Matthias

Yannik

php::bar PHP Wiki   -   Listenarchive