L(in)uchs: Problem mit NULL

Hallo,

irgendwie stehe ich auf dem Schlauch.

In einem Tabellenfeld habe ich den Wert NULL (mit phpMyAdmin geprüft). Ich lese den Datensatz mit SELECT ein und frage dieses Feld ab:

  
if (is_null($row_trm['geo_breite'])) echo "[".$row_trm['geo_breite']."] is null"; else echo "[".$row_trm['geo_breite']."] is NOT null";  

Anzeige:
[] is NOT null

Wird beim Einlesen aus NULL der Wert "" (leerer String, ist wohl was anderes als NULL)? Oder was mache ich falsch?

Gruß, L(in)uchs

  1. Soweit ich weiß ist alles was du aus der Datenbank holst ein String. Auch zahlen sind streng genommen Strings. Nur ist da PHP nicht ganz so streng und behandelt "String-Integer" als normale Integer.
    Deshalb läuft deine Prüfung ins leere.

    Gruß
    halb voller
    T-Rex

    1. Soweit ich weiß ist alles was du aus der Datenbank holst ein String.

      Gut, aber woher weiss dann phpMyAdmin, dass das Feld den Wert NULL hat? phpMyAdmin ist doch auch mit PHP programmiert.

      Also muss man mit PHP doch NULL und leeren String unterscheiden können. Wie geht das?

      Gruß
      (noch leerer) L(in)uchs

  2. Hi,

    Wird beim Einlesen aus NULL der Wert "" (leerer String, ist wohl was anderes als NULL)? Oder was mache ich falsch?

    Welche Funktion verwendest du denn zum fetchen der Datensätze?

    MfG ChrisB

    --
    RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?
    1. Welche Funktion verwendest du denn zum fetchen der Datensätze?

      mysql_fetch_array()

      1. Hallo,

        Welche Funktion verwendest du denn zum fetchen der Datensätze?
        mysql_fetch_array()

        damit ist das Verhalten nicht nachvollziehbar, siehe Hinweis im Handbuch bei den Anmerkungen.

        Und ja: eine leere Zeichenkette ist was völlig anderes als der spezielle Wert NULL.

        Freundliche Grüße

        Vinzenz

  3. Hello,

    irgendwie stehe ich auf dem Schlauch.

    In einem Tabellenfeld habe ich den Wert NULL (mit phpMyAdmin geprüft). Ich lese den Datensatz mit SELECT ein und frage dieses Feld ab:

    if (is_null($row_trm['geo_breite'])) echo "[".$row_trm['geo_breite']."] is null"; else echo "[".$row_trm['geo_breite']."] is NOT null";

      
    Das klappt mMn so nicht.  
    Entweder einen Doppelpunkt hinter der Bedingungsklammer, oder aber Blockklammern setzen.  
      
    Ich bin daher immer für die explizite Schreibweise. Die dauert in der Ausführung auch nicht länger, aber man kann sie viel schneller lesen.  
      
      if (is\_null($row\_trm['geo\_breite']))  
      {  
         echo "[" . $row\_trm['geo\_breite'] . "] is null" ;  
      }  
      else  
      {  
         echo "[".$row\_trm['geo\_breite']."] is NOT null";  
      }  
      
      
      
      
      
      
      
    Liebe Grüße aus dem schönen Oberharz  
      
      
    Tom vom Berg  
    ![](http://selfhtml.bitworks.de/Virencheck.gif)  
      
    
    -- 
     ☻\_  
    /▌  
    / \ Nur selber lernen macht schlau  
    <http://bergpost.annerschbarrich.de>
    
    1. Hi,

      if (is_null($row_trm['geo_breite'])) echo "[".$row_trm['geo_breite']."] is null"; else echo "[".$row_trm['geo_breite']."] is NOT null";

      Das klappt mMn so nicht.
      Entweder einen Doppelpunkt hinter der Bedingungsklammer, oder aber Blockklammern setzen.

      warum das? Okay, es ist im Interesse der Lesbarkeit und Wartbarkeit zu empfehlen. Aber solange der Anweisungsblock nur aus einer einzigen Anweisung besteht, darf man vom syntaktischen Standpunkt her die geschweiften Klammern auch weglassen.

      So long,
       Martin

      --
      Husten kann böse Folgen haben.
      Besonders im Kleiderschrank.
      Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
      1. Hello,

        if (is_null($row_trm['geo_breite'])) echo "[".$row_trm['geo_breite']."] is null"; else echo "[".$row_trm['geo_breite']."] is NOT null";

        Das klappt mMn so nicht.
        Entweder einen Doppelpunkt hinter der Bedingungsklammer, oder aber Blockklammern setzen.

        warum das? Okay, es ist im Interesse der Lesbarkeit und Wartbarkeit zu empfehlen. Aber solange der Anweisungsblock nur aus einer einzigen Anweisung besteht, darf man vom syntaktischen Standpunkt her die geschweiften Klammern auch weglassen.

        Das ist mir klar. Ich habe mich auch geirrt.

        Ich hatte die Schreibweise anders im Gedächtnis, ohne ein Semikolon hinter dem If-Zweig, wenn man die Klammern weglässt. Aber das war wohl bei einer anderen Programmiersprache so :-O

        Und wenn man diese Anweisung "trocken" ausprobiert, funktioniert sie auch.

        Liebe Grüße aus dem schönen Oberharz

        Tom vom Berg

        --
         ☻_
        /▌
        / \ Nur selber lernen macht schlau
        http://bergpost.annerschbarrich.de
        1. Hallöchen,

          Ich hatte die Schreibweise anders im Gedächtnis, ohne ein Semikolon hinter dem If-Zweig, wenn man die Klammern weglässt. Aber das war wohl bei einer anderen Programmiersprache so :-O

          ja, vielleicht Pascal und davon abgeleitete Sprachen. Da ist es zumindest unüblich (wenn auch nicht verboten), vor einem "end" oder "else" noch ein Semikolon zu setzen.

          Ciao,
           Martin

          --
          Life! Don't talk to me about life!
            (Marvin, the paranoid android in Douglas Adams' "The Hitchhiker's Guide To The Galaxy")
          Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
  4. hi,

    [] is NOT null

    NULL würde heißen: Der Wert ist gesetzt. Aber: Dein Wert ist eben nicht gesetzt, isset() ist Dein Freund ;)

    Hotti
    PS: In Perl würdest Du ein undef bekommen, wenn DB-Felder NULL sind.

    1. Hallo,

      NULL würde heißen: Der Wert ist gesetzt. Aber: Dein Wert ist eben nicht gesetzt, isset() ist Dein Freund ;)

      nein, der Code von L(in)uchs ist völlig in Ordnung (außer nicht besonders lesbar) und das vom OP beschriebene Verhalten läßt sich nicht nachvollziehen.
      Bedenke, dass der OP die Funktion is_null() verwendet, deren Einsatz hier völlig angemessen ist. Er weiß ja, dass es diese Spalte und damit diesen Arrayeintrag gibt.

      Beispielcode für einen XAMPP (out-of-the-box, ungesichert):

      # Ich gehe Kontextproblemen aus dem Weg  
      header("Content-type: text/plain");  
      	  
      # Verbindungsaufbau zu einem ungesicherten XAMPP :-)  
      $conn = mysql_connect('localhost', 'root', '');  
      # Die Fehlerbehandlung lasse ich der Einfachheit halber weg ...  
        
      # Mir reicht ein Datensatz mit einer Spalte, die einen NULL-Wert enthält  
      $query = 'SELECT NULL AS spalte1, 3 AS spalte2';  
      $result = mysql_query($query);  
      	  
      if ($row = mysql_fetch_array($result)) {  
          # Erste Debugausgabe  
          var_dump($row);  
          print "\n\n";  
        
          # Schauen wir, was aus L(in)uchs' Code resultiert  
          if ([link:http://de.php.net/manual/de/function.is-null.php@title=is_null]($row['spalte1'])) {  
              print "Spalte1 IS NULL\n";  
          }  
          else {  
              print "is_null konnte nicht feststellen, dass da ein NULL-Wert steht.\n";  
          }  
      }  
      
      

      #------------------------------------------------
      Ausgabe

      array(4) {
        [0]=>
        NULL
        ["spalte1"]=>
        NULL
        [1]=>
        string(1) "3"
        ["spalte2"]=>
        string(1) "3"
      }

      Spalte1 IS NULL
      #------------------------------------------------

      Und somit das gewünschte Ergebnis.
      Ja, ich habe es auch mit der unübersichtlichen "Kurzschreibweise" mit gleichem Ergebnis getestet:

      if (is_null($row['spalte1'])) echo "Spalte1 IS NULL\n"; else echo "is_null konnte nicht feststellen, dass da ein NULL-Wert steht.\n";  
      
      

      Freundliche Grüße

      Vinzenz

      1. hi,

        nein, der Code von L(in)uchs ist völlig in Ordnung (außer nicht besonders lesbar) und das vom OP beschriebene Verhalten läßt sich nicht nachvollziehen.

        Stimmt: Nicht nachvollziehbar. Hab jetzt nochmal mysqli/mysql verglichen, Spalte text ist in MySQL NULL:

        mysql> select * from test where id=677;
        +-----+------+---------------------+
        | id  | text | datum               |
        +-----+------+---------------------+
        | 677 | NULL | 2012-07-23 19:07:32 |
        +-----+------+---------------------+
        1 row in set (0.00 sec)

        mysql> select version();
        +------------------+
        | version()        |
        +------------------+
        | 5.1.40-community |
        +------------------+
        1 row in set (0.02 sec)

          
        include 'mysqli.php';  
          
        class xperlbase extends Manager_MyBase{  
        	function browse(){  
        		$res = $this->DBH->query("SELECT * FROM test WHERE id = 677");  
        		$r = mysqli_fetch_object($res);  
        		if(!isset($r->text)) print "Not Set\n";  
        		if(is_null($r->text)) print "Is NULL\n";  
        	}  
        }  
          
          
        $mb = new xperlbase;  
        $mb->browse();  
          
        $conn = mysql_connect('localhost') or die(123);  
        mysql_select_db('myweb') or die(234);;  
        $res = mysql_query("SELECT * FROM test WHERE id = 677", $conn);  
        $r = mysql_fetch_object($res);  
          
        if(!isset($r->text)) print "Not Set\n";  
        if(is_null($r->text)) print "Is NULL\n";  
          
        print_r($r);  
        
        

        Not Set
        Is NULL
        Not Set
        Is NULL
        stdClass Object
        (
            [id] => 677
            [text] =>
            [datum] => 2012-07-23 19:07:32
        )

        Version PHP
        PHP 5.3.0 (cli) (built: Jun 29 2009 21:25:23)
        Copyright (c) 1997-2009 The PHP Group
        Zend Engine v2.3.0, Copyright (c) 1998-2009 Zend Technologies

        Hotti

        1. Tach!

          if(!isset($r->text)) print "Not Set\n";
          if(is_null($r->text)) print "Is NULL\n";

          isset() funktioniert "nicht richtig", denn es liefert auch bei vorhandener Variable/Array-Element/Objekteigenschaft ein false, wenn deren Inhalt null ist. Insofern ist es nur zum Testen auf Nicht-Null-Werte geeignet. Dass es so arbeitet ist der Laxheit geschuldet, mit der einge PHP-Anwender ihren Code schreiben.

          $foo = $_POST['foo'];
            vardump(isset($foo));

          Abgesehen vom Unsinn des Umkopierens und der Tatsache, dass $foo nun definiv existiert (var_dump($GLOBALS);), egal ob $_POST['foo'] existierte oder nicht, liefert das isset() ein false, wenn durch die Nichtexistenz von $_POST['foo'] ein null in $foo zu stehen kommt.

          Dass isset() nun doch wie vorgesehen arbeitet, liegt daran, dass man die Beschreibung durch einen Zusatz an die Funktionsweise angepasst hat: Determine if a variable is set and is not NULL.

          isset() ist also eine ungeeignete Testmethode für Variablen, die null enthalten können, wenn man auf ihre Existenz prüfen will.

          print_r($r);

          print_r() eignet sich nicht zum Nachvollziehen von Inhalten wie null, false und Leerstring oder auch true und 1. Für alle drei gibt es einen Leerstring und die anderen beiden eine 1 aus. Eindeutig ist hingegen die Ausgabe von var_dump().

          dedlfix.

          1. Hello,

            isset() ist also eine ungeeignete Testmethode für Variablen, die null enthalten können, wenn man auf ihre Existenz prüfen will.

            Wie würdest Du denn auf die Existenz einer Variablen testen, die Null enthalten kann?

            Liebe Grüße aus dem schönen Oberharz

            Tom vom Berg

            --
             ☻_
            /▌
            / \ Nur selber lernen macht schlau
            http://bergpost.annerschbarrich.de
            1. Tach!

              Wie würdest Du denn auf die Existenz einer Variablen testen, die Null enthalten kann?

              isset() liefert false, egal ob sie tatsächlich existiert oder nicht. is_null() antwortet genau entgegengesetzt und wirft zusätzlich eine Notice bei Nichtvorhandensein. Selbst mit einem @ davor ist is_null() allein unbrauchbar. isset() und is_null() zu kombinieren bringt nichts.

              is_null() und Testen auf eine Fehlermeldung ist unpraktisch, weil die Aussage von error_get_last() nicht auf eine bestimmte Anweisung zurückgeführt werden kann. $php_errormsg kann man zwar löschen und anschließend auf Inhalt prüfen.

              ini_set('track_errors', 1);
                $php_errormsg = null; var_dump(@is_null($x) and !$php_errormsg);

              Doch das kann man nicht in eine Funktion auslagern, weil beim Übergeben von nicht vorhandenen $x entweder eine Notice geworfen wird oder bei Übergabe als Referenz die Variable mit Inhalt null angelegt wird.

              Bleibt am Ende wohl nur dieses Konstrukt:

              var_dump(array_key_exists('x', get_defined_vars()) and is_null($x));

              Das schaut in der aktuellen Variablenliste für den aktuellen Scope nach dem Vorhandensein des Namens der Variable und erst dann erfolgt der Test auf null. $GLOBALS statt get_defined_vars() schränkt auf den globalen Scope ein, ist also unbrauchbar. Zudem müssen andere Lösungen für Array-Elemente und Objekt-Eigenschaften gefunden werden, wenn man das braucht.

              Apropos "braucht". Man braucht sowas eigentlich nicht. Nicht vorhandene Array-Elemente können nur in $_GET/$_POST/etc. vorkommen, und da ist null kein von PHP gesetzter Wert. Ansonsten hat man doch die Kontrolle über seine Variablen, oder man macht was falsch. (Zum Fehlersuchen bekommt man mit E_ALL und var_dump() eindeutige Aussagen.)

              dedlfix.

              1. Hello,

                Apropos "braucht". Man braucht sowas eigentlich nicht. Nicht vorhandene Array-Elemente können nur in $_GET/$_POST/etc. vorkommen, und da ist null kein von PHP gesetzter Wert. Ansonsten hat man doch die Kontrolle über seine Variablen, oder man macht was falsch. (Zum Fehlersuchen bekommt man mit E_ALL und var_dump() eindeutige Aussagen.)

                Das habe ich auch erst gedacht. Aber das Problem existiert z.B. in ähnlicher Form auch bei fgetcsv().

                Im Prinzip soll NULL allerdings auch bedeuten "den Wert gibt es nicht".

                Liebe Grüße aus dem schönen Oberharz

                Tom vom Berg

                --
                 ☻_
                /▌
                / \ Nur selber lernen macht schlau
                http://bergpost.annerschbarrich.de
                1. Tach!

                  Aber das Problem existiert z.B. in ähnlicher Form auch bei fgetcsv().
                  Im Prinzip soll NULL allerdings auch bedeuten "den Wert gibt es nicht".

                  Du meinst, var_dump(str_getcsv("")); liefert ein Array mit einem null-Eintrag? Nun, dann hat das Array ja ein Element, das dir mit count(...), oder array_key_exists('0', ...) oder auch beim foreach als ein Schleifendurchlauf signalisiert wird.

                  dedlfix.