Haitan: mysqli : Überprüfen, dann abfragen

Guten Tag,
ich möchte gerne etwas in eine Datenbank schreiben vorher soll aber geprüft werden ob das eingegeben schon in einer andeeren Relation vorhanden ist.Habe nun angefangen mit mysqli (wegn prepared stmts).
Ich hätte es so gemacht:

$tmp = "test1"
                $stmt = 'SELECT * FROM test WHERE test = ?';
                $ergebnis = $db->prepare($stmt);
                $ergebnis->bind_param('s', $tmp);
                $ergebnis->execute();

if($ergebnis->fetch()){
                $ergebnis1 = $db->query( $ergebnis );
                while ($zeile = $ergebnis1->fetch_object())
                {
                    $test = $zeile->ID;
                }
            } else {
                die("Irgendetwas lief falsch.
                  <a href='javascript:history.back()'>zurück</a>");
              }
Hier würde ich das eingeben jetzt statt "test1" speichern. Das ganze funktioniert leider nicht. Kann mir wer helfen?
Danke

  1. Hi!

    ich möchte gerne etwas in eine Datenbank schreiben vorher soll aber geprüft werden ob das eingegeben schon in einer andeeren Relation vorhanden ist.

    Das ist, wenn man es in zwei Schritten macht, immer kritisch zu betrachten, weil zwischen den beiden Schritten in einer üblicherweise vorhandenen Multithread-Umgebung andere Threads dir ins Handwerk pfuschen können. Besser ist es, einen Unique-Index zu erstellen und einfach die Daten einzufügen. Wenn es dann zu einem Unique-Constraint-Fehler kommt, den du auswerten musst, weißt du, dass die Daten schon vorhanden sind. Wenn nicht, wurden sie erfolgreich hinzugefügt. Allerdings weiß ich nicht genau, was du unter "anderer Relation" verstehst. Meinst du damit einen anderen Datensatz der selben Tabelle?

    $ergebnis = $db->prepare($stmt);
                    $ergebnis->bind_param('s', $tmp);
                    $ergebnis->execute();

    Der Variablennamen $ergebnis ist irreführend, da du an die Ergebnisdatensätze erst irgendwann mit dem Fetch-Vorgang gelangst. In $ergebnis befindet sich die ganze Zeit jedoch ein (Prepared) Statement (nicht zu verwechseln mit dem SQL-Statement-String, der sich bei dir in $stmt befindet.)

    $ergebnis1 = $db->query( $ergebnis );

    Die Methode query() erwartet einen SQL-Statement-String und kein Prepared Statement.

    Hier würde ich das eingeben jetzt statt "test1" speichern.

    Diesen Satz versteh ich nicht. Magst du ihn nochmal verständlich schreiben?

    Das ganze funktioniert leider nicht. Kann mir wer helfen?

    Du solltest stets die Rückgabewerte der Funktionen auswerten und bei Indikation eines Fehlers diesen (zumindest beim Entwickeln) mit den dafür vorgesehenen Funktionen abfragen. Dann bist du auch aussagekräftiger als mit einem "funktioniert nicht". Weiterhin ist die Funktion var_dump() hilfreich, mit der man sich vom genauen Inhalt von Variablen überzeugen kann. Und natürlich ein auf E_ALL stehendes error_reporting nebst eingeschaltetem display_errors.

    Lo!

    1. hallo,
      das mit unique geht so nicht.
      Ein Beispiel wäre jmd soll seinen namen eingeben und das Land in dem er wohnt. Nur muss das Land was er eingibt in einer Tabelle(Relation) Länder stehen(diese widerum von Benutzern gefüllt wird).
      Das was ich programmieren will, ist in etwa so ähnlich gestrickt.
      Nun gibt der Benutzer z.B Deutschland ein. Ich muss überprüfen ob Deutschland in Länder drin steht. Wenn ja ist alles ok sein Name wird hinzugefügt(in Tabelle Person) , wenn nein gibt es einen Fehler aus. Das Problem was ich grundstzl habe(ich finde kein gescheites Tutorial), das ich wenn ich diese bin_param mache, ja das SQL Statemant vollständig ist. Aber wie kann ich dieses nun auswerten(Abfragen ob Werte enstehen, wenn ja diese Ausgeben).
      Mit den Fehlermedlungen.
      Bei MySql haben ich immer " echo mysql_error() "nach " mysql_query($sql); " angegeben das hat mir immer suer geholfen. Aber wie du sagst " Die Methode query() erwartet einen SQL-Statement-String und kein Prepared Statement." da scheint ja bereits mein fehler zu sein.
      Hoffe du kannst mir nun besser helfen.
      Danke
      hai

      1. Hi!

        Ein Beispiel wäre jmd soll seinen namen eingeben und das Land in dem er wohnt. Nur muss das Land was er eingibt in einer Tabelle(Relation) Länder stehen(diese widerum von Benutzern gefüllt wird).

        Die Bedingung heißt doch aber wohl, Land _und_ Name dürfen nicht doppelt vorkommen, Land und AndererName ist aber gestattet, oder? Dann kommt ein Unique-Index auf das Feld für das Land in der Ländertabelle. Desweiteren musst du ja irgendwo Land (oder ein Verweis darauf) und Name in zusammen einer zweiten Tabelle stehen haben. Dann leg auch noch einen Unique Index über diese beiden Felder.

        Nun gibt der Benutzer z.B Deutschland ein. Ich muss überprüfen ob Deutschland in Länder drin steht. Wenn ja ist alles ok sein Name wird hinzugefügt(in Tabelle Person) , wenn nein gibt es einen Fehler aus.

        Hmm, das jetzt liest sich für mich so, dass nur die in der Ländertabelle stehenden Länder vom Benutzer eingegeben werden dürfen - und zwar zu Fuß, ohne sie aus einer vorgegebenen Liste auswählen zu dürfen. Und wenn das Land nicht vorkommt, darf der Name gar nicht gespeichert werden. Oder war deine Beschreibung ein Ist-Zustand, wie du ihn gern nicht hättest?

        Das Problem was ich grundstzl habe(ich finde kein gescheites Tutorial), das ich wenn ich diese bin_param mache, ja das SQL Statemant vollständig ist. Aber wie kann ich dieses nun auswerten(Abfragen ob Werte enstehen, wenn ja diese Ausgeben).

        Nach dem Binden kommt ein Execute. Erst dieses führt das Statement aus. Dann bindest du die Ergebnisspalten an weitere Variablen und führst fetch() aus, nach jedem dieser fetch()-Aufrufe stehen in den an das Ergebnis gebundenen Variablen die Werte der einzelnen Ergebnismengen-Datensätze. Anwendungsbeispiele finden sich im PHP-Handbuch unter anderem bei mysqli::prepare(), mysqli_stmt::execute() und mysqli_stmt::fetch(). Tutorials kenne ich keine, aber wenn du was daran nicht verstehst, frag konkret nach!

        Mit den Fehlermedlungen.
        Bei MySql haben ich immer " echo mysql_error() "nach " mysql_query($sql); " angegeben das hat mir immer suer geholfen. Aber wie du sagst " Die Methode query() erwartet einen SQL-Statement-String und kein Prepared Statement." da scheint ja bereits mein fehler zu sein.

        Ja, auch für mysqli::query() gibt es mindestens ein Anwendungsbeispiel im Handbuch. Außerdem verrät das Handbuch, wenn man genau hinsieht, dass mysqli::query() als Parameter einen String haben möchte und mysqli::prepare() aber ein mysqli_stmt zurückliefert. Da kann was nicht zusammenpassen. Obendrein beschwert sich PHP in dem Fall doch recht deutlich mit

        Warning:  mysqli::query() expects parameter 1 to be string, object given in ...

        Wenn du diese Meldung nicht gesehen hast, prüfe die bereits genannten Einstellungen zum error_reporting auf deiner Entwicklungsmaschine!

        Wie man die MySQL-Fehlermeldungen unter mysqli abfragt, ist auch in den Beispielen des Handbuchs zu sehen (teilweise jedenfalls). Ansonsten such dir in der Funktionsübersicht zu mysqli die Funktionen mit error im Namen oder der Beschreibung und lies deren Beschreibung. (Am besten die englische Fassung, die deutsche ist nicht immer fehlerfrei/eindeutig übersetzt. Zumindest solltest du (vor allem die Beispiele) mit der englischen Fassung vergleichen.)

        Lo!

        1. Hallo,

          zu unique: ja, aber das ist nicht das problem. Gehen wir mal aus die DB ist "richtig" implementiert.
          Die Benutzer wählen aus einer Liste aus diese aber nicht Fest in ihrer Größe ist(d.h sie wird jederzeit erweitert von den Benutzern)

          ich habe es nun erstmal so:

          $tmp = "test1";
                           $sql = 'SELECT ID FROM test WHERE test = ?';
                           $stmt = $db->prepare($sql);
                           $stmt->bind_param('s', $tmp);
                           $stmt->execute();
                           $stmt->bind_result($id);
                       if($stmt->fetch()){
                                 echo $id;
                           } else {
                          die("Fehler<br>
                             <a href='javascript:history.back()'>back</a>");
                         }

          Nun ist es aber so:
          Das Beispiel wir um das gleiche Problem erweitert. Also die Benutzer müssen Land aus einer Tabelle auswählen und zusätlich ihren Beruf aus einer Tabelle(die ebenfalls erweitert werden kann).
          Nun tritt folgendes Problem auf:

          All data must be fetched before a new statement prepare takes place in ..

          Danke
          Hai

          1. Hi!

            zu unique: ja, aber das ist nicht das problem. Gehen wir mal aus die DB ist "richtig" implementiert.
            Die Benutzer wählen aus einer Liste aus diese aber nicht Fest in ihrer Größe ist(d.h sie wird jederzeit erweitert von den Benutzern)

            Du antwortest mir ausweichend. Geht es im Moment erst einmal oder überhaupt nur um Probleme bei der Abfrage, ohne dass ein Dateineinfügen betrachtet werden muss oder handelt es sich um Probleme bei einem vorbereitenden Abfragen zum Zwecke eines händischen Unique-Checks mit anschließendem Einfügen, ohne dass da ein expliziter Unique Index in der Datenbank existiert, (der aber ein TOCTTOU-Problem verhindern würde)?

            Nun tritt folgendes Problem auf:
            All data must be fetched before a new statement prepare takes place in ..

            Diese Meldung sagt also aus, dass alle Daten zunächst abgefragt werden müssen, bevor ein weiteres Prepare erfolgen darf. Soweit wirst du das hoffentlich verstanden haben. Wie sind deine weiteren Überlegungen, das zu bewerkstelligen?

            Es gibt zwei Wege, das zu erreichen. Der eine ist, man holt per Schleife und Fetch alle Daten ab und lagert sie irgendwo zwischen (ein Array vielleicht), macht dann die zweite Abfrage und lagert entweder auch die Daten irgendwo zwischen und verarbeitet sie dann aus diesen Zwischenlagern. Der zweite Weg ist das Verwenden von mysqli_stmt::store_result() (das wird zumindest auf der Handbuchseite zu mysqli_stmt::fetch() erwähnt, wenn auch nicht besonders ausführlich), denn diese Methode fragt im Hintergrund das Ergebnis ab und lagert es selbst zwischen, um es beim Fetch aus diesem Zwischenspeicher holen zu können und damit das DBMS seinen eigenen Ergebnispuffer für die nächste Abfrage verwenden kann.

            Lo!

            1. Hallo,
              ja es geht vorerst nur um die Abfrage.
              Es hat nun geklappt mit store_result(). Was ich mich frage aber wie gebe ich die Sachen aus, wenn mehr als eintrag ausgegeben wird?
              Danke

              Hait

              1. Hi,

                Was ich mich frage aber wie gebe ich die Sachen aus, wenn mehr als eintrag ausgegeben wird?

                Per Schleife über alle Datensätze im Ergebnis.
                Auch dazu finden sich auf den Manualseiten sicher genügend Beispiele.

                MfG ChrisB

                --
                “Whoever best describes the problem is the person most likely to solve the problem.” [Dan Roam]
                1. Hi!

                  Was ich mich frage aber wie gebe ich die Sachen aus, wenn mehr als eintrag ausgegeben wird?
                  Per Schleife über alle Datensätze im Ergebnis.
                  Auch dazu finden sich auf den Manualseiten sicher genügend Beispiele.

                  Beispielsweise bei der Methode mysqli_stmt::fetch(). Deswegen verwies und verlinkte ich ja auf sie. *seufz*

                  Lo!