Mief: MySQL / PHP Abfragefehler

Hallo Leute,
ich mache in PHP folgende MySQL-Abfrage:

$res1 = mysql_query("select * from `indexe` where `monat` = $month");  
$dsatz1 = mysql_fetch_assoc($res1);

Aber das gibt mir folgenden Fehler:

Warning: mysql_fetch_assoc() expects parameter 1 to be resource, boolean given in /var/www/****/index.php on line 13

Wo liegt da denn der Fehler? Weiter unten im Script mache ich die Abfrage einer anderen Tabelle in der selben Datenbank, was aber keinen Fehler gibt.

  1. Hi,

    $res1 = mysql_query("select * from indexe where monat = $month");

    $dsatz1 = mysql_fetch_assoc($res1);

    
    >   
    > Aber das gibt mir folgenden Fehler:  
    >   
    > Warning: mysql\_fetch\_assoc() expects parameter 1 to be resource, boolean given in /var/www/\*\*\*\*/index.php on line 13  
    >   
    > Wo liegt da denn der Fehler?  
      
    In der fehlenden Fehlerbehandlung. Die Query ist fehlgeschlagen. Das ignorierst Du.  
    Und Du gibst im Fehlerfall auch nicht die von MySQL generierte Fehlermeldung aus: mysql\_error() wäre da sinnvoll.  
      
    Vermutung: $month enthält einen String, nicht eine Zahl. Und es existiert keine Spalte in der Tabelle, die den Namen trägt, der als String in $month steht.  
      
    cu,  
    Andreas
    
    -- 
    [Warum nennt sich Andreas hier MudGuard?](http://MudGuard.de/)  
    [O o ostern ...](http://ostereier.andreas-waechter.de/)  
      
    Fachfragen per Mail sind frech, werden ignoriert. Das Forum existiert.  
    
    
    1. Das war alles nicht der Fehler. Hab ihn "zufällig" entdeckt. Ich hatte in der Funktion mysql_select_db() ausversehen den Tabellennamen angeben und nicht den Datenbanknamen. Weiter unten vor dem nächsten Abfrage-Block hatte ich die Funktion nochmal mit dem richtigen Inhalt.

      1. Hi,

        Das war alles nicht der Fehler. Hab ihn "zufällig" entdeckt.

        Weil eben keinerlei Fehlerbehandlung stattfindet. mysql_error hätte Dir vermutlich gemeldet, daß keine Verbindung existiert ...

        cu,
        Andreas

        --
        Warum nennt sich Andreas hier MudGuard?
        O o ostern ...
        Fachfragen per Mail sind frech, werden ignoriert. Das Forum existiert.
  2. Hi,

    RTFM.

    "Für SELECT […] gibt mysql_query() eine Kennung resource bei Erfolg zurück oder FALSE bei Fehlern."

    Weiter unten:

    <?php  
    $result = mysql_query('SELECT * WHERE 1=1');  
    if (!$result) {  
        die('Ungültige Anfrage: ' . mysql_error());  
    }  
    ?>
    

    Anstelle von die(); sollte da eine sinnvolle Fehlerbehandlung rein.

    ~dave

  3. Tach!

    Warning: mysql_fetch_assoc() expects parameter 1 to be resource, boolean given in /var/www/****/index.php on line 13
    Wo liegt da denn der Fehler?

    Generelle Frage: Wie betreibt man Fehlersuche? Die Meldung ist ja schön einfach. Es wird eine Ressource erwartet, stattdessen offensichtlich ein Boolean übergeben. Das schauen wir uns doch mal an:

    var_dump($res1);

    Ausgabe: false

    Aha! Und wo kommt das false her?

    $res1 = mysql_query("select * from indexe where monat = $month");

    $dsatz1 = mysql_fetch_assoc($res1);

      
    mysql\_query() hat es geliefert. Na sowas, warum macht es das denn? [Handbuch befragen!](de.php.net/manual/en/function.mysql-query.php) Da steht dann, dass false bei einem Fehler zurückgegeben wird und wie man an den Fehlermeldungstext kommt (sowie obendrein noch, dass mal bitte auf mysqli oder PDO umsteigen soll).  
      
    Anhand des MySQL-Meldungstextes sieht man dann, woran MySQL gescheitert ist und kann den Fehler beseitigen. Ist nun alles gut? Nur dann, wenn man auch daran glaubt, dass im Sommer immer schönes Wetter ist. Fehler treten nicht nur bei selbstverschuldetem Handeln auf. Dem MySQL-Server kann aus verschiedenen Gründen unpässlich sein. Das äußert sich nicht nur durch einen gescheiterten Verbindungsaufbau, sondern auch in aus anderen als Syntax-Gründen nicht durchlaufenden Querys. Deshalb ist es wichtig, sich über solche Ausfallszenarien Gedanken zu machen und diese in seinem Script-Ablauf zu berücksichtigen. Ein reines Ausgeben der Fehlermeldung (immer wieder auch mit einem sofortigen Abbruch zu sehen) ist nur zum Debugging sinnvoll. Für den laufenden Betrieb ist das keine Information, die einen Benutzer etwas angeht (und auch kein angemessenes Verhalten).  
      
      
    dedlfix.
    
    1. مرحبا

      Dem MySQL-Server kann aus verschiedenen Gründen unpässlich sein. Das äußert sich nicht nur durch einen gescheiterten Verbindungsaufbau, sondern auch in aus anderen als Syntax-Gründen nicht durchlaufenden Querys. Deshalb ist es wichtig, sich über solche Ausfallszenarien Gedanken zu machen und diese in seinem Script-Ablauf zu berücksichtigen.

      Wenn der Verbindungsaufbau schief geht, reicht ja

      if (mysqli_connect_errno())

      Gibt es auch das Szenario, dass die Verbindung zwar hergestellt wird, aber ein bestimmtes Feld nicht angesprochen werden kann? Wie reagiert man darauf? Greift hier noch mysqli_connect_errno()?
      Aktuell speichere ich in meinem CMS fehler (401,403,404,410; 500 geht nicht, weil da nichts mehr geht) in der Datenbank, kann es hier passieren, dass obwohl die Verbindung Ok ist, dass Feld für die Fehler in der Datenbank nicht angesprochen werden kann? Wo soll ich dann diese Fehler speichern, wohl im Errorlog? Aber woran erkenne ich, dass dieses eine Feld nicht angesprochen werden konnte, und daher das Script als Alternative den Fehler im Error_log speichern soll?

      mfg

      1. مرحبا

        Aber woran erkenne ich, dass dieses eine Feld nicht angesprochen werden konnte, und daher das Script als Alternative den Fehler im Error_log speichern soll?

        Mich weiss.

        Ich speichere die Fehler mittels einer Funktion. Wenn das speichern in der DB dort schief geht, dann muss das Script den Fehler im error_log speichern.

          function insertError ($status) {  
            $_connect->query("INSERT INTO ...");  
          
            # folgendes fehlt noch in meiner Funktion  
            if (mysqli_affected_rows($_connect) == 1) {  
              # Eintrag ok  
            } else {  
              # Fehler aufgetreten, im error_log speichern  
            }  
            return;  
          }
        

        mfg

        1. Tach!

          function insertError ($status) {

          $_connect->query("INSERT INTO ...");

            
          Auch im Falle eines Fehlers beim INSERT gibt die query-Funktion ein false zurück.  
            
            
          dedlfix.
          
          1. مرحبا

            function insertError ($status) {

            $_connect->query("INSERT INTO ...");

            
            >   
            > Auch im Falle eines Fehlers beim INSERT gibt die query-Funktion ein false zurück.  
              
            Wäre ja auch ok. Hauptsache, mir gehen keine aufgetretenen Fehler verloren. Aktuell weiss ich bspw. nicht, ob Server bei mir abschmieren, da ich diese Fehler garnicht behandle.  
            Die Idee mit der Mail finde ich gut. Das wäre am schnellsten und einfachsten realisiert. Aber warum in einer anderen Sprache? Kann man Überhaupt bei einem 500er Error noch mails senden? Ich weiss nicht, wie ich das testen soll.  
              
            mfg
            
            1. Tach!

              Die Idee mit der Mail finde ich gut. Das wäre am schnellsten und einfachsten realisiert. Aber warum in einer anderen Sprache? Kann man Überhaupt bei einem 500er Error noch mails senden? Ich weiss nicht, wie ich das testen soll.

              Wann kommt denn ein 500er? Wenn im Server irgendwas ziemlich kaputt ist. Vielleicht ist es eine Fehlkonfiguration PHPs. Dann ist es nicht sehr sinnig, PHP als Scriptsprache zum Fehlermelden zu verwenden. Vielleicht läuft ja Perl noch, recht sicher aber ein Shell Script. Das muss ja nichts weiter tun, als eine Mail zu versenden und es muss lediglich noch der CGI-Mechanismus im Apachen laufen.

              dedlfix.

              1. مرحبا

                Wann kommt denn ein 500er?

                Ich bekomme 500er nur zusehen, wenn ich an der Seite rumfummel, sprich an der htaccess rumspiele. Ansonsten konnte ich bislang nie einen 500er erzwingen.

                Vielleicht ist es eine Fehlkonfiguration PHPs. Dann ist es nicht sehr sinnig, PHP als Scriptsprache zum Fehlermelden zu verwenden.

                Kann das mitten im Betrieb passieren? Das einzige Szenario, wo ich mir das vorstellen kann, ist, wenn der Hoster da rumfummelt. Aber selbst wenn der Hoster es kaputt konfiguriert, wird er doch zusehen, dass das schnell gefixt wird, oder?

                recht sicher aber ein Shell Script. Das muss ja nichts weiter tun, als eine Mail zu versenden und es muss lediglich noch der CGI-Mechanismus im Apachen laufen.

                Da müsste ich mich erstmal in die Shell-programmierung einlesen, da habe ich überhaupt keine Ahnung von. Hast du einen Tipp?

                mfg

                1. Tach!

                  Ich bekomme 500er nur zusehen, wenn ich an der Seite rumfummel, sprich an der htaccess rumspiele. Ansonsten konnte ich bislang nie einen 500er erzwingen.

                  Ja, Fehlkonfigurationen in der .htaccess sind Ursache von 500ern. Inwieweit man in derselben fehlerhaften .htaccess noch ein ErrorDocument verbiegen kann, weiß ich nicht. Ganz bestimmt nicht mehr nach dem Syntaxfehler. Wenn die Ursache eine Endlosschleife beim Rewriten ist, dann wird das ErrorDocument vermutlich noch ziehen.

                  Vielleicht ist es eine Fehlkonfiguration PHPs. Dann ist es nicht sehr sinnig, PHP als Scriptsprache zum Fehlermelden zu verwenden.
                  Kann das mitten im Betrieb passieren?

                  Ich weiß es nicht. 500er gibt es auch, wenn das Script und/oder PHP keine ordentlichen Header produziert. Das sieht man als PHPer normalerweise nicht, weil PHP selbst die HTTP-Header erstellt. Aber wenn es warum auch immer abstürzt?

                  Da müsste ich mich erstmal in die Shell-programmierung einlesen, da habe ich überhaupt keine Ahnung von. Hast du einen Tipp?

                  Mail senden sollte nicht sehr schwer sein. Das sind mit Shebang zwei Zeilen.

                  dedlfix.

                  1. مرحبا

                    Ja, Fehlkonfigurationen in der .htaccess sind Ursache von 500ern. Inwieweit man in derselben fehlerhaften .htaccess noch ein ErrorDocument verbiegen kann, weiß ich nicht.

                    Genau der Punkt bereitet mir Bauchschmerzen.

                    Ich hab's gerade mal probiert:

                    ErrorDocument 500 http://webmaster.test/error_500.pl  
                      
                    RewriteCond %{REQUEST_FILENAME} !-f  
                    RewriteCond %{REQUEST_FILENAME} !-d  
                    RewriteRule .  /indexer.php [L,QSA]  
                    # /indexer.php gibt es nicht, so dass ein 500er ausgegeben wird, und auch der richtige (error_500.pl).
                    

                    Jetzt stellt sich die Frage, ob man das mit einem Perl-Script realisiert, was eine Perl-Installation voraussetzt, oder doch mit PHP? Selbst wenn ein anderes Script den Fehler verursacht, ist es doch eher unwahrscheinlich, dass man diesen Fehler in die "error_500.pl" oder "error_500.php" übernimmt.
                    Allerdings, wenn der Server komplett in die Knie geht, dann geht nichts mehr, aber wie oft kommt sowas vor? Da ich es bislang nie ausgewertet habe, weiss ich da überhaupt nichts drüber.

                    Mail senden sollte nicht sehr schwer sein. Das sind mit Shebang zwei Zeilen.

                    Ich hatte vor Jahren mal etwas an Perl rumgefingert, war mir aber dann doch zu kompliziert, wegen Windows, Xampp und der Shebang. Eine Lösung in PHP würde ich daher schon vorziehen.

                    mfg

                    1. Tach!

                      ErrorDocument 500 http://webmaster.test/error_500.pl

                      Bist du sicher, dass du zu einer externen URL weiterleiten willst?

                      RewriteCond %{REQUEST_FILENAME} !-f
                      RewriteCond %{REQUEST_FILENAME} !-d
                      RewriteRule .  /indexer.php [L,QSA]

                      /indexer.php gibt es nicht, so dass ein 500er ausgegeben wird, und auch der richtige (error_500.pl).[/code]

                      Da hätte ich jetzt aber einen 404er erwartet.

                      Jetzt stellt sich die Frage, ob man das mit einem Perl-Script realisiert, was eine Perl-Installation voraussetzt, oder doch mit PHP? Selbst wenn ein anderes Script den Fehler verursacht, ist es doch eher unwahrscheinlich, dass man diesen Fehler in die "error_500.pl" oder "error_500.php" übernimmt.

                      Die Frage nach dem Risiko kann ich nicht beantworten. Wie gesagt, es reicht eine kleine Benachrichtigung per Mail, was man mit einem Zweizeiler-Shell-Script hinbekommt.

                      Allerdings, wenn der Server komplett in die Knie geht, dann geht nichts mehr, aber wie oft kommt sowas vor? Da ich es bislang nie ausgewertet habe, weiss ich da überhaupt nichts drüber.

                      Dann setz dir Monit auf, oder nimm eine vom Hoster angebotene Überwachung (sicher erst ab Server und nicht bei Webspace zu bekommen).

                      dedlfix.

                      1. مرحبا

                        ErrorDocument 500 http://webmaster.test/error_500.pl
                        Bist du sicher, dass du zu einer externen URL weiterleiten willst?

                        Ohne Domain ging es nicht. Alle anderen Fehler kann man ohne die Domain umleiten, nur der 500er funktioniert, zumindest bei mir, nicht ohne die Domain.

                        ErrorDocument 401 /index.php?error_document=401  
                        ErrorDocument 403 /index.php?error_document=403  
                        ErrorDocument 404 /index.php?error_document=404  
                        ErrorDocument 500 http://webmaster.test/error_500.php
                        

                        Anders ging es nicht.

                        Die Frage nach dem Risiko kann ich nicht beantworten. Wie gesagt, es reicht eine kleine Benachrichtigung per Mail, was man mit einem Zweizeiler-Shell-Script hinbekommt.

                        Könntest du ein Bsp. posten, ich finde keinen Zweizeiler, mit dem ich das lösen könnte.

                        Dann setz dir Monit auf, oder nimm eine vom Hoster angebotene Überwachung

                        Monit klingt gut, das werde ich mir mal näher ansehen. Danke für den Tipp.

                        mfg

                        1. Tach!

                          ErrorDocument 500 http://webmaster.test/error_500.pl
                          Bist du sicher, dass du zu einer externen URL weiterleiten willst?
                          Ohne Domain ging es nicht. Alle anderen Fehler kann man ohne die Domain umleiten, nur der 500er funktioniert, zumindest bei mir, nicht ohne die Domain.

                          Probier es mit einem URL-Pfad, der nach außerhalb des "kaputten" Verzeichnisses zeigt.

                          [...] kleine Benachrichtigung per Mail, was man mit einem Zweizeiler-Shell-Script hinbekommt.
                          Könntest du ein Bsp. posten, ich finde keinen Zweizeiler, mit dem ich das lösen könnte.

                          #!/bin/bash
                          echo "Ich bin kaputt." | mail -s "Nachricht von deinem Server" name@example.com

                          dedlfix.

                          1. مرحبا

                            Probier es mit einem URL-Pfad, der nach außerhalb des "kaputten" Verzeichnisses zeigt.

                            Wie meinst du das?
                            Ich habe es gerade nochmal probiert, und jetzt geht's nicht mal mehr mit der Domain. Dann wird, wie du schon schriebst, auf die Adresse weitergeleitet. Ich habe es auch mit einem neuen cgi-bin Verzeichnis probiert, war auch ein fehlschlag. Da mir das zu Bunt ist mit Windows, habe ich mir jetzt kurzer Hand eine Domain registriert, auf der ich das morgen nochmal ausgiebig teste.

                            #!/bin/bash
                            echo "Ich bin kaputt." | mail -s "Nachricht von deinem Server" name@example.com

                            Das muss ich morgen mal auf der neuen Domain testen, auf meiner Windows-Kiste wird das nichts.

                            mfg

                            1. مرحبا

                              #!/bin/bash
                              echo "Ich bin kaputt." | mail -s "Nachricht von deinem Server" name@example.com

                              hast du sowas schon gemacht? Ich kriege es einfach nicht auf die Kette.

                              http://e-ypsilon.net/test

                              Die Seite "test" gibt es nicht, aber das ist egal, da ich einen 500er provozieren will, keinen 404er. Also leite ich alles wie gehabt auf die nicht existierende "indexer.php". Damit bekomme ich zwar einen 500er, aber nicht meinen eigenen.

                              # .htaccess (der gesamte Inhalt)  
                              ErrorDocument 500 /cgi-bin/error_500.pl  
                                
                              RewriteEngine On  
                              RewriteBase /  
                                
                              RewriteCond %{REQUEST_FILENAME} !-f  
                              RewriteCond %{REQUEST_FILENAME} !-d  
                              RewriteRule .  /indexer.php [L,QSA]
                              

                              Und das ErrorDocument (/cgi-bin/error_500.pl):

                              #!/bin/bash  
                              echo "Ich bin kaputt." | mail -s "Nachricht von deinem Server" mail@example.de
                              

                              Ich komme nicht mal direkt auf das ErrorDocument. Was mache ich falsch? Die Domain ist bei 1&1 gehostet ('ne Inklusiv-Domain).

                              mfg

                              1. Tach!

                                Und das ErrorDocument (/cgi-bin/error_500.pl):

                                Es ist zwar kein Perl sondern Shell-Script, aber das stört nicht weiter. Wichtig ist nur, dass für das cgi-bin
                                  Options +ExecCGI
                                  AddHandler cgi-script .cgi .pl
                                oder ähnlich konfiguriert ist, also dass bestimmte Dateiendungen als CGI-Script behandelt werden. Alternativ kann bei einem reinen CGI-Verzeichnis auch
                                  Options ExecCGI
                                  SetHandler cgi-script
                                konfiguriert sein, dann wird alles als CGI-Script behandelt. Obendrein muss auch noch das Executable-Bit bei den Scripts gesetzt sein.

                                Eigentlich sollte das alles schon passend eingerichtet sein, nur für das Executable-Bit musst du selbst sorgen.

                                dedlfix.

                                1. مرحبا

                                  Options +ExecCGI
                                    AddHandler cgi-script .cgi .pl

                                  Es ist echt zum Mäuse melken. Gestern hatte ich Stundenlang rumprobiert, irgendwie mein eigenes ErrorDocument zu erzwingen. Hat zwar nicht wirklich geklappt, aber ich habe 4 Mails vom Servererror bekommen, obwohl meine Fehlerseite nicht angezeigt wurde. Ich weiss aber nicht, wie ich diese Mails gesendet bekommen habe, muss das nochmal rekonstruieren.

                                  Eigentlich sollte das alles schon passend eingerichtet sein, nur für das Executable-Bit musst du selbst sorgen.

                                  Dateirechte meinst du, oder? Ich habe das cgi-bin-Verzeichnis und alles darin Stumpf auf 777 gesetzt, allerdings habe ich noch mit ein paar anderen Sachen zu kämpfen. Aber ich bleib dran, bis morgen sollte ich Resultate haben.

                                  mfg

                                  1. Tach!

                                    Ich habe das cgi-bin-Verzeichnis und alles darin Stumpf auf 777 gesetzt,

                                    0777 ist selten eine gute Idee. Solange kein anderer die Datei beschreiben soll, reicht 755 und 644 (ohne Ausführen). Bitte nicht immer ohne Not Scheunentore aufreißen.

                                    dedlfix.

                                    1. مرحبا

                                      Ich habe das cgi-bin-Verzeichnis und alles darin Stumpf auf 777 gesetzt,

                                      0777 ist selten eine gute Idee. Solange kein anderer die Datei beschreiben soll, reicht 755 und 644 (ohne Ausführen). Bitte nicht immer ohne Not Scheunentore aufreißen.

                                      Danke für den Hinweis, werde ich berücksichtigen.

                                      mfg

                                  2. مرحبا

                                    Es ist echt zum Mäuse melken. Gestern hatte ich Stundenlang rumprobiert, irgendwie mein eigenes ErrorDocument zu erzwingen. Hat zwar nicht wirklich geklappt, aber ich habe 4 Mails vom Servererror bekommen, obwohl meine Fehlerseite nicht angezeigt wurde. Ich weiss aber nicht, wie ich diese Mails gesendet bekommen habe, muss das nochmal rekonstruieren.

                                    Und hiermit gebe ich offiziell auf ;)

                                    Ich kriege es einfach nicht gebacken.

                                    mfg

      2. Tach!

        Gibt es auch das Szenario, dass die Verbindung zwar hergestellt wird, aber ein bestimmtes Feld nicht angesprochen werden kann?

        Ja, theoretisch. Praktisch hat man die Berechtigungen korrekt gesetzt und geprüft. Eher relevant dürfte werden, dass irgendeine außergewöhnliche Randbedingung zum Abbruch der Query führt, wie Speichermangel oder dass der Backup-Mechanismus just in dem Augenblick den Server angehalten hat.

        Wie reagiert man darauf? Greift hier noch mysqli_connect_errno()?

        Nein. Man wertet die Rückgabewerte der verwendeten Funktionen aus. Ein sinnvolles spezielles Reagieren kann es nur geben, wenn man einen bestimmten Fehler eingeplant hat. Ansonsten kann man nur allgemein reagieren und das Script mit einer Tröstmeldung in Richtung Anwender geordnet beenden. Gegebenenfalls kann man Alternativen vorschlagen. Nicht unbedingt die Konkurrenz, sondern was der Anwender machen kann, um doch noch zu seinem (und unserem) Ziel zu gelangen.

        Aktuell speichere ich in meinem CMS fehler (401,403,404,410; 500 geht nicht, weil da nichts mehr geht) in der Datenbank,

        500 geht generell schon, nur wäre es sicher sinnvoll, das 500-er ErrorDocument mit einer anderen Script-Sprache abzuarbeiten, die dann eine Mail sendet. Dann weiß man wenigstens, dass sowas aufgetreten ist und kann sich die zugehörige Meldung im ErrorLog anschauen, wenn man darauf zugreifen darf.

        kann es hier passieren, dass obwohl die Verbindung Ok ist, dass Feld für die Fehler in der Datenbank nicht angesprochen werden kann?

        Siehe oben.

        Wo soll ich dann diese Fehler speichern, wohl im Errorlog?

        Du musst sie nicht unbedingt speichern. Eine Mail kann auch die Fehler-Information zum Admin befördern.

        Aber woran erkenne ich, dass dieses eine Feld nicht angesprochen werden konnte, und daher das Script als Alternative den Fehler im Error_log speichern soll?

        Du bekommst den konkreten Fehlermeldungstext wie üblich durch Auswerten der bekannten Informationsquellen. Im Falle von MySQLi ist es mysqli::$error oder mysqli_stmt::$error. PHP-Fehler und deren Texte bekommt man über einen eigenen Error-Handler.

        dedlfix.