philip.p: DB-Abfrage: WHERE mit mehreren optionalen Parametern

Hi,

wenn ich eine DB-Abfrage mache und die Ausgabe auf bestimmte Felder beschränken möchte, mache ich das ja mittels WHERE.

sprintf("SELECT feld_x FROM table WHERE feld_x = '%s' AND feld_y = '%s'") ... ;

Wie mache ich das aber nun, wenn ich je nach Auswahl des Benutzers (per Formular) verschiedene Felder wählen will? D.h. der eine Benutzer will Daten von feld_x, der andere von feld_x und feld_y, ein dritter nur von feld_y usw. Dann muss ich ja individuell bei WHERE die Felder aufführen.

Wie funktioniert das?

Ich kann ja kaum mittels if prüfen, ob feld_x oder feld_y oder feld_x und feld_y gewählt wurden, und je nachdem unterschiedliche Select-Abfragen durchführen.

Also sowas:

  if($_POST['feld_x'] == "ok" && $_POST['feld_y'] != "ok")  
  {  
    "SELECT feld_x FROM table WHERE feld_x = '%s'";  
  }  
  elseif($_POST['feld_x'] != "ok" && $_POST['feld_y'] == "ok")  
  {  
    "SELECT feld_x FROM table WHERE feld_y = '%s'";  
  }  
  elseif($_POST['feld_x'] == "ok" && $_POST['feld_y'] == "ok")  
  {  
    "SELECT feld_x FROM table WHERE feld_x = '%s' AND feld_y = '%s'";  
  }

Bei zwei Feldern mag das ja noch gehen - aber bei mehreren wird das doch arg lang und unübersichtlich. Da gibts ja immer 2^Feldanzahl Optionen.

  1. Heyho!

    Im Grunde doch. Fuer jede Auswahl ein Argument dazufügen.

    Pseudocode:

    query = 'Select name from personal'

    if feld1
    {
     where =  'where gehalt > x'
    }

    if feld2
    {
     wenn where existiert dann
     {
      where = where + 'AND'
     }
     where = where + geschlecht = 'w'
    }

    ...

    --
    "Die Diebesgilde beklagte sich darueber, dass Mumm in aller Oeffentlichkeit behauptet hatte, hinter den meisten Diebstaehlen steckten Diebe."
          - T. Pratchett
  2. Hallo,

    Wie mache ich das aber nun, wenn ich je nach Auswahl des Benutzers (per Formular) verschiedene Felder wählen will? D.h. der eine Benutzer will Daten von feld_x, der andere von feld_x und feld_y, ein dritter nur von feld_y usw. Dann muss ich ja individuell bei WHERE die Felder aufführen.

    klar erkannt. :-)

    Wie funktioniert das?

    Baue dein SQL-Statement schrittweise zusammen. Fang an mit dem konstanten Teil vor der WHERE-Klausel:

    $query = "SELECT feld_x FROM table WHERE ";

    Jetzt gehst du deine Auswahlkriterien durch. Da es mehrere sind, bietet sich ein Array an, um diese zu speichern. Also legen wir zunächst ein leeres Array an, das wir dann Schritt für Schritt bestücken.

    $condition = array();
      if (isset($_POST['feld_x']))
         $condition[] = "feld_x = '" . mysql_real_escape_string($_POST['feld_x']) . "'";
      if (isset($_POST['feld_y']))
         $condition[] = "feld_y = '" . mysql_real_escape_string($_POST['feld_y']) . "'";
      if (isset($_POST['feld_z']))
         $condition[] = "feld_z = '" . mysql_real_escape_string($_POST['feld_z']) . "'";

    Du erkennst die Regelmäßigkeit? - Und zum Schluss bauen wir das Statement zusammen, indem wir die gesammelten Bedingungen jeweils mit einem "AND" dazwischen zusammenfügen und an das bereits angefangene SQL-Statement anhängen:

    $sql .= implode(" AND ", $condition);

    Nur den Fall, dass überhaupt kein Auswahlkriterium eingegeben wurde, solltest du noch abprüfen - in diesem Fall würde das bislang sture Vorgehen natürlich einen SQL-Fehler provozieren.

    Bei zwei Feldern mag das ja noch gehen - aber bei mehreren wird das doch arg lang und unübersichtlich. Da gibts ja immer 2^Feldanzahl Optionen.

    Stimmt. Versuche in solchen Fällen immer, das Problem möglichst systematisch anzugehen und Regelmäßigkeiten zu finden. Sobald man solche Regelmäßigkeiten erkannt hat, ist die Realisierung meist nicht mehr so dramatisch.

    So long,
     Martin

    --
    F: Was ist wichtiger: Die Sonne oder der Mond?
    A: Der Mond. Denn er scheint nachts. Die Sonne dagegen scheint tagsüber, wenn es sowieso hell ist.
    1. Aaaaaaja - also gibt es im Grunde keine direkte Lösung im Select-Befehl :)

      Ich hatte ja auch schon mit Platzhaltern rumprobiert. D.h. im Select-Befehl stehen alle Felder, wurde ein Feld aber nicht gewählt, dann wird ein Platzhalter eingesetzt (if(!isset(...)) feld_y = '*';), aber das geht wohl auch nicht.

      Naja, dann eben doch halbumständlich :D

      Vielen Dank euch beiden.

      1. Hello,

        Aaaaaaja - also gibt es im Grunde keine direkte Lösung im Select-Befehl :)

        Wie soll es die geben? Die möglichen Kombinationen sind immens!

        Liebe Grüße aus dem schönen Oberharz

        Tom vom Berg

        --
        Nur selber lernen macht schlau
        http://bergpost.annerschbarrich.de
        1. Wie soll es die geben? Die möglichen Kombinationen sind immens!

          Hätte ja sein können, dass sich da jemand etwas Schlaues ausgedacht hat :)

    2. Also wenn ich mir das jetzt zusammenstückle, dann liefert mir das diesen Fehler:

      Warning: mysql_num_rows(): supplied argument is not a valid MySQL result resource

      Der Code dazu sähe so aus:

            if($kapa_anzahl  != "") { $select_anzahl[] = "kapazitaet = " . mysql_real_escape_string($kapa_anzahl); }  
            if($herst_anzahl != "") { $select_anzahl[] = "hersteller = '" . mysql_real_escape_string($herst_anzahl) . "'"; }  
            if($preis_anzahl != "") { $select_anzahl[] = "preis <= " . mysql_real_escape_string($preis_anzahl); }  
        
            $result = "SELECT * FROM sticks";  
            if($kapa_anzahl  != "" || $herst_anzahl  != "" || $preis_anzahl  != "")  
            {  
              $result .= " WHERE ";  
              $result .= implode(" AND ", $select_anzahl);  
            }  
        
            $result = mysql_num_rows($result);
      

      Wenn ich mir aber $result mit echo ausgebe, ist dort eigentlich alles korrekt zusammengesetzt: SELECT * FROM sticks WHERE kapazitaet = 4 AND hersteller = 'Intenso' AND preis <= 35

      1. Ups, mysql_query vergessen ;-)

        1. Hallo,

          Ups, mysql_query vergessen ;-)

          nicht nur ...

          Hast Du schon einmal daran gedacht, die modernere und leistungsfähigere mysqli-Erweiterung zu nutzen?

          Freundliche Grüße

          Vinzenz

          1. nicht nur ...

            Oay, danke.

            Hast Du schon einmal daran gedacht, die modernere und leistungsfähigere mysqli-Erweiterung zu nutzen?

            Ja, aber bisher konnte ich mich noch erfolgreich dagegen wehren :)

            Irgendwann, wenn ich mal Zeit habe, befasse ich mich damit.

            Bin jetzt erst mal froh, dass mir die Vorschläge hier im Forum 140 Zeilen Code erspart haben :)

      2. Hallo Philipp,

        Warning: mysql_num_rows(): supplied argument is not a valid MySQL result resource

        if($kapa_anzahl  != "") { $select_anzahl[] = "kapazitaet = " . mysql_real_escape_string($kapa_anzahl); }

        if($herst_anzahl != "") { $select_anzahl[] = "hersteller = '" . mysql_real_escape_string($herst_anzahl) . "'"; }
              if($preis_anzahl != "") { $select_anzahl[] = "preis <= " . mysql_real_escape_string($preis_anzahl); }

        $result = "SELECT * FROM sticks";
              if($kapa_anzahl  != "" || $herst_anzahl  != "" || $preis_anzahl  != "")
              {
                $result .= " WHERE ";
                $result .= implode(" AND ", $select_anzahl);
              }

        Verbesserungsvorschlag:

        $result sollte eher $statement heißen.

        Fehler:

        Das Statement ist wie üblich an den MySQL-Server schicken.

        Prüfe, ob MySQL die Anweisung erfolgreich ausführen konnte.

        Wenn ja

        #    Schau' Dir das Resultat bzw. Informationen zum Resultat an

        Fehler:

        #    Es ist keine gute Idee, im Falle des Erfolgs die Ressourcenkennung
        #    mit der Zahl der Datensätze zu überschreiben

        $result = mysql_num_rows($result);

          
          
          
        Freundliche Grüße  
          
        Vinzenz
        
      3. Hi!

        if($kapa_anzahl  != "") { $select_anzahl[] = "kapazitaet = " . mysql_real_escape_string($kapa_anzahl); }
              if($preis_anzahl != "") { $select_anzahl[] = "preis <= " . mysql_real_escape_string($preis_anzahl); }

        Bei diesen beiden Zeilen hast du eine Sicherheitslücke, weil du den Kontextwechsel nicht richtig berücksichtigst. Ich hab da grad einen Artikel in Vorbereitung, der auch diese Problematik berücksichtigt: siehe "Zahlen im (My)SQL-Statement" im Abschnitt Falsch erkannte / behandelte Kontextwechsel (Vorabversion).

        Lo!

  3. Hello,

    gibt es ein konkretes Abfrageformular oder ist die Frage eher wissenschaftlicher Natur?

    Unterschiede gibt es üblicherweise zwischen

    Spalte wird überhaupt abgefragt        (im Gegensatz zu->)
       Spalte soll leer sein oder NULL [1]
       Spaltenwert stimmt mit abgefragtem überein
       Spaltenwert fängt mit abgefragtem an
       Spaltenwert enthält den abgefragtem
       Spaltenwert endet mit dem abgefragten

    Spaltenwert < als abgefragter
       Spaltenwert > als abgefragter

    Verknüpfung mit AND
       Verknüpfung mit OR

    Bedingung im Abfragefeld umkehren -> NOT

    usw.

    [1] NULL und false müssen gesondert behandelt werden.

    Liebe Grüße aus dem schönen Oberharz

    Tom vom Berg

    --
    Nur selber lernen macht schlau
    http://bergpost.annerschbarrich.de