Nick: PHP/ MySQL Select mit IF/ CASE

Hallo zusammen

Gerne möchte ich folgenden Code erweitern. Mein Problem ist, dass die $_POST Variable manchmal leer ist, ist dies der Fall funktioniert die Abfrage nicht mehr. Habe ich eine Möglichkeit, die Abfrage so zu verändern, dass die where Funktion nur dan verwendet wird wenn die $_POST Variable einen Wert enthält?

  
$sql = "SELECT * FROM blog where thema ='" . $_POST['etwas'] . "'";  

Ich weiss ich könnte einfach 2 Abfragen machen und mit PHP IF und ELSE trennen. Eine MySQL Lösung (Case/ If) wäre aber eleganter.

Danke und Gruss, Nick

  1. Hi!

    Gerne möchte ich folgenden Code erweitern. Mein Problem ist, dass die $_POST Variable manchmal leer ist, ist dies der Fall funktioniert die Abfrage nicht mehr. Habe ich eine Möglichkeit, die Abfrage so zu verändern, dass die where Funktion nur dan verwendet wird wenn die $_POST Variable einen Wert enthält?

    Ja, aber das ist dann eine PHP-Geschichte, weil du das Statement mal mit und mal ohne WHERE schreiben musst.

    $sql = "SELECT * FROM blog where thema ='" . $_POST['etwas'] . "'";

    Zudem solltest du dich mit dem Thema Kontextwechsel beschäftigen, denn einen unbekannten Wert direkt in ein Statement einzufügen ist grob fahrlässig.

    Ich weiss ich könnte einfach 2 Abfragen machen und mit PHP IF und ELSE trennen. Eine MySQL Lösung (Case/ If) wäre aber eleganter.

    Nein, wäre sie nicht, denn du bekommst das WHERE nicht mit SQL weg. Du kannst nur auf LIKE umsteigen und im Falle von Leerstring ein % verwenden. Das macht die Sache aber nicht weniger kompliziert zu durchschauen.

    Lo!

    1. Hi!

      Zudem solltest du dich mit dem Thema Kontextwechsel beschäftigen, denn einen unbekannten Wert direkt in ein Statement einzufügen ist grob fahrlässig.

      Link vergessen: http://wiki.selfhtml.org/wiki/Artikel:Kontextwechsel

      Lo!

      1. Danke für die Hinweise und Eure Hilfe.

        Die Idee mit LIKE finde ich einleuchtend. Also müsste theoretisch die SQL Abrage irgendwie wie folgt aussehen?

          
        select * from xxx where yyy LIKE '%IFNULL('$varibale', '')';  
        
        

        Ich weiss das es so nicht klappt, aber irgendwie in die Richtung?

        1. Hi!

          Ich weiss das es so nicht klappt, aber irgendwie in die Richtung?

          Du solltest erstmal klar beschreiben, was du willst. Möchtest du nun, wie aus dem Ausgangsposting zu lesen ist entweder nach dem eingegebenen Wert selektieren oder ansonsten alles haben oder möchtest du bei Leereingabe nach einem anderen von dir vorgegebenen Default-Wert suchen, so wie ich es aus jenem Posting lese.

          select * from xxx where yyy LIKE '%IFNULL('$varibale', '')';

          So geht es schonmal gar nicht. Mit dem ersten ' eröffnest du ein Stringliteral. Darin werden keine Funktionsnamen und dergleichen erkannt. Erst mit dem nächsten ' beendest du das Stringliteral und bist wieder im Code-Modus. Es ist wichtig, dieses Prinzip zu verstehen, und auch, dass ein unbeachtetes ' dir das Stringliteral vorzeitig beenden kann, und der Rest dann als Code interpretiert wird.

          Lo!

    2. Nein, wäre sie nicht, denn du bekommst das WHERE nicht mit SQL weg. Du kannst nur auf LIKE umsteigen und im Falle von Leerstring ein % verwenden. Das macht die Sache aber nicht weniger kompliziert zu durchschauen.

      Habe eigentlich dass gemeint:
      IF($_POST...){ Select ... etwas}
      else { select ... etwas anderes}

      Aber eben, dass ist halt nicht so elegant. Vielen Dank für Eure Hilfe!

      1. Hi!

        Habe eigentlich dass gemeint:
        IF($_POST...){ Select ... etwas}
        else { select ... etwas anderes}

        Aber eben, dass ist halt nicht so elegant.

        Eine Fallunterscheidung bekommst du mit der IF()-Funktion unter MySQL hin

        ... WHERE feld = IF(Leer-Vergleich, dies, jenes)

        Das bedeutet aber, dass MySQL vielleicht keinen Index für die Spalte verwenden kann, weil es jedes Mal den Ausdruck ausrechnet. Wenn du das mit PHP machst, muss dieses genau einmal den Fall prüfen und MySQL bekommt ein fertiges Statement, ohne selbst rechnen zu müssen.

        $sql = sprintf("SELECT * FROM table WHERE feld = '%s'",
                         mysql_real_escape_string(empty($_POST['feld']) ? 'wasanderes' : $_POST['feld']));

        Lo!

        1. Mein Server streikt leider bei mysql_real_escape_string. Habe es jetzt wie folgt gelöst, auch wenn nicht ganz so elegant wie Gedacht.

            
          isset($_POST['suchen'])?$suchen=$_POST['suchen']:$suchen="";  
            
          $sql = "SELECT * FROM blog where keywords LIKE '%" . $suchen . "%' ORDER BY guid DESC";  
          
          

          @dedlfix
          Werde mich noch mit deinem Hinweis beschäftigen.

          1. Hallo,

            Mein Server streikt leider bei mysql_real_escape_string.

            was bedeutet das konkret? Verwendest du überhaupt mySQL, oder vielleicht einen anderen SQL-Dialekt?

            isset($_POST['suchen'])?$suchen=$_POST['suchen']:$suchen="";

            Das ist eine untypische Art, den ternären Operator einzusetzen. Üblich wäre:

            $suchen = isset($_POST['suchen']) ? $_POST['suchen'] : "";

            So long,
             Martin

            --
            Lieber mit Betty im Wald
            als mit Waldi im Bett.
            Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
            1. Ach so, ich verwende natürlich MySQLi und nicht MySQL. Soweit habe ich gar nicht gedacht. Blöd von mir das ich das nicht angegeben habe. Sorry und vielen Dank für Deine Hilfe!

  2. Hallo!

      
    $_POST['etwas'] = "sonstwas; DROP TABLE blog;";  
    
    

    $sql = "SELECT * FROM blog where thema ='" . $_POST['etwas'] . "'";

      
    Plonk.  
      
      
      
    Liebe Grüße aus Norddeutschland.
    
    -- 
    ie:{ fl:( br:> va:} ls:[ fo:| rl:? n4:~ ss:) de:> js:| ch:? sh:( mo:) zu:) 
    
    1. Hi!

      $_POST['etwas'] = "sonstwas; DROP TABLE blog;";

      $sql = "SELECT * FROM blog where thema ='" . $_POST['etwas'] . "'";
      Plonk.

      Das geht so nicht. Wenn man nicht mysqli_multi_query() verwendet, ergibt das nur einen Syntaxfehler, weil MySQL die Ausführung von zwei Statements in einer Query ablehnt. Man kann aber immer noch genügend Änderungen am SELECT-Statement vornehmen, um die Ergebnismenge zu beeinflussen oder beispielsweise an Daten aus anderen Tabellen zu gelangen.

      Lo!

  3. Tach auch.

    Mein Problem ist, dass die $_POST Variable manchmal leer ist, ist dies der Fall funktioniert die Abfrage nicht mehr. Habe ich eine Möglichkeit, die Abfrage so zu verändern, dass die where Funktion nur dan verwendet wird wenn die $_POST Variable einen Wert enthält?

    $sql = "SELECT * FROM blog where thema ='" . $_POST['etwas'] . "'";

      
    Ich verwende überlicherweise sowas:  
      
    ~~~php
      
    $filter = isset($_POST['etwas']) ? "WHERE thema = '" . $dbh->escape_string($_POST['etwas']) . "'" : '';  
    $sql = "SELECT * FROM blog $filter";  
    
    

    Mit einer Anweisung wäre z.B. folgendes möglich:

      
    $var = ""; // Hinweise zum Kontextwechsel wurden bereits gegeben!  
    $sql = "SELECT * FROM blog WHERE IF (LENGTH('$var') = 0, 1, thema = '$var')";  
    
    

    Idee: wenn im Query der String '$var' (Hinweise zum Kontext!) leer ist, dann gibt das IF-Statement immer Wahr zurück.
    Ich finde das aber weder schöner zu lesen als das "dynamische SQL" in meinem ersten Beispiel noch ist es schneller (da die Datenbank für jede Ergebniszeile das IF-Statement prüft).

    Bis die Tage,
    Matti

    1. Tach auch.

      Hab nochmal drüber nachgedacht. Das zweite Beispiel ist äquivalent zu:

        
      $sql = "SELECT * FROM blog WHERE LENGTH('$var') = 0 OR thema = '$var'";  
      
      

      Bis die Tage,
      Matti