Ankündigung

Einklappen
Keine Ankündigung bisher.

[Erledigt] MySQLi Count Abfrage

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • [Erledigt] MySQLi Count Abfrage

    Hey zusammen,

    ich hab gerade einen alten Skript von mir rausgekramt und wollte diesen auf den neusten Stand bringen. Nach den ersten paar Zeilen kam natürlich auch eine Datenbankabfrage, die ich von MySQL auf MySQLi umstellen will.

    Der Connect zur Datenbank steht, das war kein Problem.

    Nun bin ich an einem Punkt, bei dem ich eine Eingabe (E-Mail Adresse) mit der DB abgleiche um herauszufinden, ob der Eintrag bereits existiert.

    Jetzt habe ich 2, bzw. eigentlich 3 verschiedene Lösungsansätze, die auch alle funktionieren und mir das richtige Ergebnis (nach mehreren Test) liefern. Ausgabe jeweils per var_dump();


    Variante 1: Prepared mit affected_rows (Variante 2: oder num_rows)

    PHP-Code:
    $sql 'SELECT
                  COUNT(EMail)
                FROM
                  Benutzer
                WHERE
                  EMail = ?'
    ;
        
    // Abfrage wird vorbereitet
        
    $abfrage $db->prepare($sql);
        
    // Fehlende Variablen zuweisen
        
    $abfrage->bind_param('s',$email);
        
    // Abfrage wird ausgeführt
        
    $abfrage->execute();
        
    // Ergebnisse werden gespeichert
        
    $abfrage->store_result();
        
    // Wenn ein Eintrag existiert -> E-Mail Adresse bereits hinterlegt -> Fehler
        
    if($abfrage->affected_rows>0)    // Bzw. if($abfrage->num_rows>0)
        
    $fehler[] = "Die eingegebene E-Mail Adresse existiert bereits und kann nicht verwendet werden"

    Variante 3: Query mit num_rows

    PHP-Code:
    $sql 'SELECT
                  EMail
                FROM
                  Benutzer
                WHERE
                  EMail = "'
    .$email.'"';
        
    // Query ausführen
        
    $abfrage $db->query$sql );
        
    // Wenn ein Eintrag existiert -> E-Mail Adresse bereits hinterlegt -> Fehler
        
    if($abfrage->num_rows>0
        
    $fehler[] = "Die eingegebene E-Mail Adresse existiert bereits und kann nicht verwendet werden"

    Eine 4. Variante gibt es nicht (Variante 3 mit affected_rows). Dort erscheint folgender Hinweis:
    Notice: Undefined property: mysqli_result::$affected_rows... Wobei var_dump() auch hier das richtige Ergebnis liefert.


    Welche der 3 Varianten ist die "beste" (über das Wort brauchen wir nicht streiten ^^). Mir geht es um puncto Sicherheit, Übersichtlichkeit und Schnelligkeit. Schnelligkeit aber eher weniger. Ich glaube kaum, dass man bei einer der 3 Varianten einen Unterschied empfindet.

    Von der Sicherheit her würde ich zu Variante 1 oder 2 tendieren, wegen den Prepared Statments. Von der Übersicht eher zu 3, weil weniger Code.

    Laut Manual sollte affected_rows bei INSERT, UPDATE und DELETE benutzt werden, scheint aber auch bei SELECT zu funktionieren. Für SELECT bietet sich daher eher num_rows an.


    Alles in allem tendiere ich derzeit zu Variante 2 (Prepared mit num_rows).

    Sehen das andere genauso?

    Gruß Steffen

  • #2
    Zitat von sNaiK274 Beitrag anzeigen
    Laut Manual sollte affected_rows bei INSERT, UPDATE und DELETE benutzt werden, scheint aber auch bei SELECT zu funktionieren.
    Das wäre ein Bug.

    Alles in allem tendiere ich derzeit zu Variante 2 (Prepared mit num_rows).
    Wäre auch richtig. Allerdings weiß ich nicht, was sich bei Dir hinter $db angesiedelt hat.

    Kommentar


    • #3
      Danke schonmal für die Antwort.

      Zitat von meikel Beitrag anzeigen
      Wäre auch richtig. Allerdings weiß ich nicht, was sich bei Dir hinter $db angesiedelt hat.
      Naja, eigentlich nichts wildes. Ein Standard-Script zum Verbinden mit einer Datenbank und Fehlerausgabe.

      PHP-Code:
      <?
      /* Mit Hilfe dieser Datei wird die Verbindung zur Datenbank hergestellt */

      $dbhost="xxx";     // Datenbank-Host
      $dbname="xxx";  // Datenbank-Name
      $dbuser="xxx";        // Datenbank-Benutzer
      $dbpass="xxx";  // Datenbank-Passwort

      // Verbinden mit MySQLi
      $db = @new mysqli($dbhost, $dbuser, $dbpass, $dbname);

      // Fehlerausgabe bei gescheiterter Verbindung
      if ($db->connect_errno)
      {
          echo 'Es konnte keine Datenbankverbindung hergestellt werden!<br />';
          echo 'Folgender Fehler ist aufgetreten: (' . $db->connect_errno . ') ' . $db->connect_error;
          exit;
      }
      ?>
      Aber auch dafür nehme ich gerne Verbesserungsvorschläge an

      Gruß Steffen

      Kommentar


      • #4
        Zitat von sNaiK274 Beitrag anzeigen
        Aber auch dafür nehme ich gerne Verbesserungsvorschläge an
        Ist schön kurz und müßte funktionieren. Könntest ja auch die mysqli Klasse ableiten:
        PHP-Code:
        <?php

        class db extends mysqli {

          public function 
        __construct(){
            
        $acc getSqlAccount();
            
        parent::__construct($acc['host'], ...);
        # usw.
          
        }
        }
        ?>
        Und falls Du mal auf PDO umsteigen solltest:

        PHP-Code:
        <?php
        class db extends pdo {
        # etwas anderer constructor -> DSN methode
        }

        Kommentar


        • #5
          Danke für den Vorschlag, aber mit Klassen steh ich derzeit noch auf absolutem Kriegsfuß. Deinen Code versteh ich leider absolut gar nicht

          Müsste mich vorher grundlegend damit befassen und einige Tutorials lesen, ansonsten bau ich dadurch mehr Fehler ein, als das die Sache sich für mich erstmal lohnen würde.

          Solange mein Code sicher ist, funktioniert und eine einigermaßen gute Performance an den Tag legt bin ich erstmal zufrieden

          Könnte überflüssig sein, habe aber in die SQL-Anweisung noch ein LIMIT 1 eingesetzt. Sollte man sich diesen Zusatz sparen, wenn eh sicher ist, dass die E-Mail Adressen in der DB unique sind?


          Gruß Steffen

          Kommentar


          • #6
            Zitat von sNaiK274 Beitrag anzeigen
            Könnte überflüssig sein, habe aber in die SQL-Anweisung noch ein LIMIT 1 eingesetzt.
            Limit 1 erinnert mich an "geschweißtes mit Nieten". Wenn eine Abfrage nur ein Ergebnis haben soll und Du befürchtest, es könne doch mehr als eins sein, dann taugt das DB Design nix. Oder Du hast Heinzelmännchen... <ggg>

            Sollte man sich diesen Zusatz sparen, wenn eh sicher ist, dass die E-Mail Adressen in der DB unique sind?
            Wenn die (zB) email unique sein soll, dann setze das Spaltenattribut auf unique. Dann verhindert MySQL zuverlässig Doubletten.

            Kommentar


            • #7
              Zitat von meikel Beitrag anzeigen
              Wenn die (zB) email unique sein soll, dann setze das Spaltenattribut auf unique. Dann verhindert MySQL zuverlässig Doubletten.
              Ab und zu unterschätze ich einfach die Macht der MySQL Datenbank

              LIMIT 1 ist demnach wieder rausgeflogen. Spalte wurde auf Unique gesetzt. Wunderbar, beim Anlegen der gleichen E-Mail Adresse über phpmyadmin fliegt mir "#1062 - Duplicate entry" um die Ohren, sehr gut. Schätze mal der Code und die Meldung werden dann auch beim mysqli_error im Skript ausgegeben, richtig?

              Kommentar


              • #8
                Zitat von sNaiK274 Beitrag anzeigen
                Schätze mal
                Nicht schätzen. Du willst doch Programmierer werden und kein Statistiker. Teste es einfach.

                Kommentar


                • #9
                  Recht hast du. Daher mal sämtliche Überprüfungen ausgeklammert und versucht in die Datenbank zu pressen... keine Chance.
                  1062: "Duplicate entry..."
                  Immerhin hatte ich mit meiner Schätzung Recht, aber so Dinge werde ich in Zukunft prüfen und nicht auf gut Glück versuchen. Nochmals vielen Dank

                  Gruß Steffen

                  Kommentar


                  • #10
                    Zitat von sNaiK274 Beitrag anzeigen
                    Variante 1: Prepared mit affected_rows (Variante 2: oder num_rows)

                    PHP-Code:
                    $sql 'SELECT
                                  COUNT(EMail)
                                FROM
                                  Benutzer
                                WHERE
                                  EMail = ?'
                    ;
                        
                    // Abfrage wird vorbereitet
                        
                    $abfrage $db->prepare($sql);
                        
                    // Fehlende Variablen zuweisen
                        
                    $abfrage->bind_param('s',$email);
                        
                    // Abfrage wird ausgeführt
                        
                    $abfrage->execute();
                        
                    // Ergebnisse werden gespeichert
                        
                    $abfrage->store_result();
                        
                    // Wenn ein Eintrag existiert -> E-Mail Adresse bereits hinterlegt -> Fehler
                        
                    if($abfrage->affected_rows>0)    // Bzw. if($abfrage->num_rows>0)
                        
                    $fehler[] = "Die eingegebene E-Mail Adresse existiert bereits und kann nicht verwendet werden"
                    warum affected_rows/num_rows nehmen, wenn der count im Query steckt?

                    nichtsdestotrotz ist die Absicherung auf MySQL-Seite (über UNIQUE) vorzuziehen.

                    mal als Beispiel in PDO
                    PHP-Code:
                    $pdo = new PDO(...); // hier kommen dann die tatsächlichen Verbindungsdaten rein
                    $ps $pdo->prepare('SELECT
                                  COUNT(EMail)
                                FROM
                                  Benutzer
                                WHERE
                                  EMail = :mail'
                    );
                    // EMail ist ein String, da können wir lazy bind machen
                    $ps->execute(array("mail" => $email));
                    // oder explizit
                    // $ps->bindValue("mail", $email, PDO::PARAM_STR);
                    // $ps->execute();
                    $count $ps->fetchColumn(); 

                    Kommentar

                    Lädt...
                    X