2 vorbereitete Anweisungen, 2 gespeicherte Prozeduren, 1 mysqli Verbindung

8

Problem

So rufen Sie zwei gespeicherte MySQL-Prozeduren in derselben mysqli-Verbindung auf, indem Sie vorbereitete Anweisungen verwenden (oder eine andere Abfragemethode, die genauso sicher gegen SQL-Injektionen ist) , ohne die folgenden Fehler zu erhalten:

%Vor%

Der Code ist online unter tutorialspoint

verlinkt

Geschichte

Ich mache ein PHP-Backend mit einer MySQL-Datenbank. Ich habe zwei Ergebnisse, die ich von einer Abfrage erhalten möchte: eine Liste von wöchentlichen Zusammenfassungen und eine Zusammenfassung aller Wochen.

%Vor%

Früher habe ich nur die wöchentlichen Zusammenfassungen in einer Datenbanktabelle gespeichert und eine gespeicherte Prozedur verwendet, um die Zusammenfassung aller wöchentlichen Zusammenfassungen zu erhalten. In meinem PHP-Code habe ich einfach alle Zeilen in der Tabelle week ausgewählt und dann die gespeicherte Prozedur getWeeksSummary aufgerufen.

Jetzt muss ich in der Lage sein, die Daten in den wöchentlichen Zusammenfassungen zu filtern. Ich habe eine einfache SELECT ... FROM week durch eine gespeicherte Prozedur getWeeks() ersetzt, um alle wöchentlichen Zusammenfassungen zu berechnen.

Code

%Vor%

Dieser Code funktionierte einwandfrei, wenn die erste vorbereitete Anweisung SELECT week, sales, commission, ... FROM week WHERE a=?, b=?, c=?; anstelle von CALL getWeeks(?,?,?); war. Jetzt bekomme ich diese Fehler:

%Vor%

Versuche

1) Fehlgeschlagen: Ich habe für die zweite Abfrage ein neues Anweisungsobjekt $stmt2 verwendet. Gleiche Fehler.

2) Erfolg: Ich habe die Verbindung mysqli geschlossen und vor der zweiten Anweisung eine neue geöffnet. Eine zweite mysqli Verbindung mit einer eigenen vorbereiteten Anweisung läuft zwar gut, aber der Code zum Verbinden mit der Datenbank wird komplett getrennt gehalten, so dass das nicht wirklich hilft.

3) Fehlgeschlagen: Aus reiner Neugier bin ich zu meinem ursprünglichen working Code zurückgekehrt und habe die Anweisungen neu geordnet und die gespeicherte Prozedur eingefügt Anweisung vor der SELECT -Anweisung. Gleiche Fehler. So ist die Verbindung mysqli in Ordnung mit Abfragen vor der gespeicherten Prozedur, mag aber nichts nach der gespeicherten Prozedur.

4) Fehlgeschlagen: Ich habe versucht, $mysqli->next_result(); nach der ersten Anweisung zu setzen. Gleiche Fehler. Wenn ich jedoch query() anstelle von prepare() verwende, um die gespeicherten Prozeduren aufzurufen, kann% code_de% tatsächlich beide gespeicherten Prozeduren ausführen. Ich würde gerne eine vorbereitete Anweisung verwenden, da sie gegen SQL-Injektionen hilft.

Unerwünschte mögliche Lösungen

A): Ich könnte es in zwei Aufrufe an das Back-End aufteilen, aber die Zusammenfassungen würden am Frontend nicht synchron sein, wenn Daten aktualisiert werden.

B): Ich könnte sie in eine gespeicherte MySQL-Prozedur einfügen und sie dann in PHP trennen, aber ich brauche sie auch separat, also wäre der gleiche Code dort zweimal.

C): Ich könnte aufhören, vorbereitete Anweisungen zu verwenden, aber ich kenne keine anderen Möglichkeiten, SQL-Injektionen zu vermeiden.

Hilfe

Irgendwelche Vorschläge?

    
Ray 25.09.2015, 02:10
quelle

2 Antworten

5

Nun, ich werde versuchen, für den -Fragetitel zu antworten, vorausgesetzt, dass in der ersten Anweisung keine normale Abfrage, sondern eine der beiden zuvor erwähnten gespeicherten Prozeduren aufgerufen wurde.

Nachdem Sie eine gespeicherte Prozedur aufgerufen haben, müssen Sie immer eine zusätzliche leere Ergebnismenge verschieben, die von jeder gespeicherten Prozedur zurückgegeben wird:

%Vor%

Fügen Sie auch nach dem ersten vorbereiteten Funktionsaufruf einen zusätzlichen fetch () hinzu, nachdem Sie Ihre Daten erhalten haben:

%Vor%

, da Sie den Ergebnissatz, der auf der Serverseite wartet, "freigeben" müssen. Es könnte auf viele Arten geschehen, aber am einfachsten wäre es, fetch () noch einmal aufzurufen, oder, genauer gesagt, müssen Sie fetch () aufrufen, bis FALSE zurückgegeben wird, um anzuzeigen, dass im Resultset keine Zeilen mehr übrig sind . Sie tun es [still] in den anderen Schnipsel, wenn Sie fetch() in der while -Schleife aufrufen, aber hier, wenn Sie nur eine Zeile holen, müssen Sie sie explizit aufrufen.

Es gibt einen anderen Weg, viel bequemer: Verwenden Sie get_result() (falls verfügbar), um alle Ihre Probleme gleichzeitig zu lösen. Statt dieses langen und windigen Codes braucht man im Moment nur vier Zeilen:

%Vor%

get_result() gibt diese wartende Ergebnismenge frei und erlaubt Ihnen gleichzeitig, fetch_object() method zu verwenden, wodurch Sie das resultierende Objekt in nur einer Zeile erhalten.

    
Your Common Sense 25.09.2015 07:59
quelle
1

Wenn Sie die mysqli -Dokumentation lesen, heißt das, dass $stmt->free_result() ist es, den von $stmt->store_result() . Da der Code store_result() nicht verwendet, werden durch das Entfernen von free_result() die Fehler behoben.

Natürlich heißt es auch, store_result() immer dann zu verwenden, wenn eine Abfrage eine Ergebnismenge zurückgibt. Ich verstehe wirklich nicht warum (etwas, was mit Pufferung zu tun hat), aber da diese zwei vorbereiteten Anweisungen und gespeicherten Prozeduren ohne store_result() funktionieren, ist das Problem gelöst.

Ich bin immer noch neugierig, warum es nicht mit store_result() und free_result() funktioniert, aber zumindest gibt es jetzt einen funktionierenden Code. Hier ist der modifizierte Code bei tutorialspoint.

Als Nebenbemerkung verwenden Sie anstelle von zwei vorbereiteten Anweisungen mit zwei gespeicherten Prozeduren eine vorbereitete Anweisung, um Variablen

festzulegen %Vor%

Verwenden Sie dann diese Variablen in Abfragen, um die gespeicherten Prozeduren aufzurufen

%Vor%     
Ray 02.10.2015 02:59
quelle