Hackerboard Wiki HaboBlog
Hackerboard bei Facebook Hackerboard bei Google+ Hackerboard bei Twitter

[HaBo]

 
(Web-) Design und webbasierte Sprachen Tipps & Tricks, Designabgleich, HTML & Javascript, Flash, ASP, PHP, Perl/CGI...

Funktion zur Datenbankabfrage zeigt unterschiedliches Verhalten

Diskussion: Funktion zur Datenbankabfrage zeigt unterschiedliches Verhalten im Forum (Web-) Design und webbasierte Sprachen, in der Kategorie Web, Network & Multimedia Palace; Anzeige Hi Community, ich schreibe momentan eine kleine Webapplikation. So weit, so gut. Das Schema ist folgendes: erst wird geprüft, ...

Antwort
Alt 05.12.10, 22:44   #1 (permalink)
 
Registriert seit: 08.12.06
zero-9 Leistung: Facit NTK
Likes: 0
Standard Funktion zur Datenbankabfrage zeigt unterschiedliches Verhalten

Anzeige

Hi Community,

ich schreibe momentan eine kleine Webapplikation. So weit, so gut. Das Schema ist folgendes: erst wird geprüft, ob $_POST["user"] und $_POST["password"] gesetzt sind und auch richtig sind.

PHP-Code:
if((!empty($_POST["user"])) and (!empty($_POST["password"]))) 
Wenn ja, fragt er die Daten ab und erzeugt eine Tabelle in der die Daten geordnet wiedergegeben werden. Weiterhin wird $_SESSION[logged_in] = 1 gesetzt.

Wenn die index.php nochmals aufgerufen wird und $_SESSION["logged_in"] = 1 gesetzt ist werden die Daten direkt abgerufen, also ohne Passwortabfrage.

PHP-Code:
elseif($_SESSION["logged_in"] == 1
In beiden Fällen (also nach dem Login und dem Wiederaufrufen mit $_SESSION["logged_in"] = 1) wird die Funktion showUserData($user) aufgerufen. Sie ruft die Daten ab, die mit dem übergebenen User in Verbindung stehen.
Das Komische: logge ich mich ein, ruft er die Daten normal ab. Keine Fehlermeldung, alles super.
Klicke ich jetzt auf einen Link und gehe wieder auf die index.php scheitert showUserData($user) und gibt aus:

Zitat:
Warning: mysql_fetch_object(): supplied argument is not a valid MySQL result resource
Ich weiß, was die Meldung bedeutet, weiß aber nicht warum sie erscheint. Der Username wird per Sessionvariable übergeben und den query string den ich mir vor dem query ausgeben lasse, stimmt.
Ich weiß momentan nicht mehr weiter. Hat jemand eine Idee? In jedem Fall ist der Query valide, also warum scheitert er trotzdem, sodass die obige Fehlermeldung kommt? Warum funktioniert das direkt nach dem Login und später nicht mehr?

P.S.: Alle Datenbankaufrufe der Applikation werden mit mysql_close geschlossen.
zero-9 ist offline   Mit Zitat antworten
Alt 05.12.10, 22:51   #2 (permalink)
Member of Honour
 
Benutzerbild von beavisbee
 
Registriert seit: 22.02.07
beavisbee Leistung: Pentium IIIbeavisbee Leistung: Pentium IIIbeavisbee Leistung: Pentium IIIbeavisbee Leistung: Pentium III
beavisbee eine Nachricht über ICQ schicken
Likes: 77
Standard

ohne den gesamten Code zu sehen, kann man nur mutmaßen...

1.) auch wenn's nicht direkt zum Problem gehört - ich hoffe, du nutzt nicht direkt $_POST['user'] und $_POST['password'] in der SQL-Query - da wären nämlich Tür und Tor für SQL-Injections offen (dazu gibt es hier im Forum schon Threads)

2.) was sagt mysql_errno() und mysql_error()?

also z.B.
PHP-Code:
<?php
$result 
mysql_query('SELECT ....');
if (!
$result) {
  throw new 
Exception('Datenbank-Fehler: [' mysql_errno() . '] ' mysql_error());
}
?>
beavisbee ist gerade online   Mit Zitat antworten
   
HaBOT
 
- Anzeige -

Werbung ist gerade online    
Alt 05.12.10, 22:55   #3 (permalink)
 
Benutzerbild von metax.
 
Registriert seit: 22.01.07
metax. Leistung: 8086
metax. eine Nachricht über ICQ schicken
Likes: 10
Standard

Hi,

ohne Quellcode von der betreffenden Funtkion kann man nur raten.
Ich rate mal: Du machst irgendwas in deinem MySQL-Aufruf, um Fehlermeldungen zu verdecken (bzw. hast das PHP Error Reporting auf einen zu niedrigen Wert gestellt), z.B. durch ein Voranstellen eines "@"-Zeichens vor den Aufruf (oder durch ein ErrorReporting ohne E_NOTICE).
Aus irgendeinem Grund schlägt dein MySQL-Aufruf fehl (warum, kann man wieder nur raten; vermutlich hast du entweder das Query nicht korrekt zusammengebaut, obwohl du das behauptest, oder die Verbindung ist zu oder irgendein anderer der mannigfaltigen MySQL-Fehler tritt auf), es wird keine Fehlermeldung geschmissen und dein MySQL-Result-Objekt ist null.

Ergo, wenn du fundiertere Hilfe möchtest: Poste mal den PHP-Code um die Abfrage, vor allem auch das zusammenbauen des Query-Strings.
Zusätzlich kannst du direkt nach der Query mit mysql_errno() und mysql_error herausfinden, welchen Fehler der MySQL-Aufruf genau gemacht hat.
Dann sieht man weiter.

mfg, metax.

edit: Wie immer zu langsam ...
__________________
Wenn keiner zuschaut, teile ich heimlich durch Null!
Meine Homepage: Planet Metax | meine Bilder: DeviantArt | Twitter
metax. ist offline   Mit Zitat antworten
Alt 05.12.10, 23:06   #4 (permalink)
Themenstarter
 
Registriert seit: 08.12.06
zero-9 Leistung: Facit NTK
Likes: 0
Standard

Scheinbar wirft das bei mir keine Exceptions. Ich kriege keine Fehlernummer auf bei $objects (quasi mein "$result"). Ich poste mal den Code für die Abfrage.

PHP-Code:
function showUserData($user)
  {
    
$connection DBLogin();
    
$clean_user mysql_real_escape_string($user);
    
$query "SELECT amount, purpose, day, month, year FROM spendings WHERE id IN (SELECT id FROM user WHERE user = \"".$clean_user."\")";
    echo 
$query;
    
$objects mysql_query($query);
    echo 
var_dump($objects);
    echo 
"<table>";
    echo 
"<tr><th>Purpose</th><th>Amount</th></tr>";
    while(
$row mysql_fetch_object($objects))
    {
      
      
$zahl sprintf("%01.2f"$row->amount);
      echo 
"<tr><td>".$row->purpose."</td><td>".$zahl." €</td></tr>";
    }
    echo 
"</table>";
    
    
mysql_close($connection);
  } 
Das ist die besagte Funktion. Nach dem Einloggen: alles Klasse. Rufe ich aber eine andere Seite auf und kehre zu ihr zurück, schlägt die Abfrage fehl. var_dump sagt, dass $objects (die den Rückgabewert von mysql_query aufnimmt) boolean und false ist. Für gewöhnlich habe ich das, wenn ein Fehler in der SQL - Syntax ist, aber die ist richtig.

Im Anhang mal die index.php.
Angehängte Dateien
Dateityp: txt index.txt (957 Bytes, 3x aufgerufen)
zero-9 ist offline   Mit Zitat antworten
Alt 05.12.10, 23:18   #5 (permalink)
 
Benutzerbild von metax.
 
Registriert seit: 22.01.07
metax. Leistung: 8086
metax. eine Nachricht über ICQ schicken
Likes: 10
Standard

Was liefert denn mysql_error() und mysql_errno() nach der Abfrage mit mysql_query() zurück?
Siehe auch hier: http://de.php.net/mysql_query
mysql_query() liefert genau dann false zurück, wenn ein Fehler auftritt.
Also musst du noch den von uns vorgeschlagenen Code einbauen und die Fehlermeldung herausfinden.
__________________
Wenn keiner zuschaut, teile ich heimlich durch Null!
Meine Homepage: Planet Metax | meine Bilder: DeviantArt | Twitter

Geändert von metax. (05.12.10 um 23:22 Uhr)
metax. ist offline   Mit Zitat antworten
Alt 05.12.10, 23:42   #6 (permalink)
Themenstarter
 
Registriert seit: 08.12.06
zero-9 Leistung: Facit NTK
Likes: 0
erledigt

Ich danke für eure Hilfe: ich habe es! Habe wohl vorhin einen Fehler bei der Integration von beavisbees Code gemacht, nun hat die Exception aber gegriffen. Der Fehler: keine Datenbank selektiert.

Das Problem ist folgendes: Bei der Login - Prozedur kommt es zum Aufruf von mysql_select_db.
Wenn ich irgendwann wieder auf die Seite gehe, prüft er ob USER und PASSWORD gePOSTet wurden. Wenn nein, prüft er auf eine Session. Die ist vorhanden. Das Problem: ich rufe direkt showUserData dann auf. Dem geht aber kein mysql_select_db voraus. Und daraufhin läuft das Query natürlich ins Leere.

Danke für eure schnelle Hilfe.
zero-9 ist offline   Mit Zitat antworten
Alt 06.12.10, 09:26   #7 (permalink)
Member of Honour
 
Benutzerbild von beavisbee
 
Registriert seit: 22.02.07
beavisbee Leistung: Pentium IIIbeavisbee Leistung: Pentium IIIbeavisbee Leistung: Pentium IIIbeavisbee Leistung: Pentium III
beavisbee eine Nachricht über ICQ schicken
Likes: 77
Standard

bitte, bitte, gern geschehen.

und noch zwei kleine Tipps bezüglich deiner SQL-Query:

Code:
"SELECT amount, purpose, day, month, year FROM spendings WHERE id IN (SELECT id FROM user WHERE user = \"".$clean_user."\")"
verschachtelte Queries sollte man nur da verwenden, wo wirklich nötig...

gehe ich richtig in der Annahme, dass in der user-Tabelle immer nur jeder User einmal vorkommt und eine eindeutige ID hat?

Code:
"SELECT
    s.amount,
    s.purpose,
    s.day,
    s.month,
    s.year
FROM
    spendings s,
    user u
WHERE
    s.id=u.id
    AND
    u.user = \"".$clean_user."\"
"
oder

Code:
"SELECT
    s.amount,
    s.purpose,
    s.day,
    s.month,
    s.year
FROM
    spendings s
  INNER JOIN user u ON (s.id=u.id)
WHERE
    u.user = \"".$clean_user."\"
"
hab's jetzt aus Zeitgründen nicht probiert, aber wenn ich mich nicht vertippt habe, dann sollte das so funktionieren.

in der Tabelle "user" ist das Feld "id" ja sicherlich der PrimaryKey und somit schon ein Index, in der Tabelle "spendings" solltest du dann der Performance wegen auf das Feld "id" noch 'nen Index legen.

mehr zu JOINs:
http://dev.mysql.com/doc/refman/5.1/de/join.html
http://aktuell.de.selfhtml.org/artik...nbanken/joins/


und du verwendest sowohl in der Tabelle "user" als auch in der Tabelle "spendings" das Feld "id" für die User-ID... wenn du in der Tabelle "spendings" das Feld "user_id" nennst, kann ein dritter, der über deine Datenbank drüber schaut, wesentlich einfacher nachvollziehen, wie die Tabellen miteinander verknüpft sind... wenn du die Felder in beiden Tabellen gleich benannt haben möchtest, dann würde sich eben in beiden Tabellen "user_id" oder "uid" empfehlen - macht die Sache für Außenstehende einfach wesentlich einfacher lesbar
beavisbee ist gerade online   Mit Zitat antworten
Alt 06.12.10, 18:31   #8 (permalink)
Member of Honour
 
Benutzerbild von GrafZahl
 
Registriert seit: 28.05.10
GrafZahl Leistung: OpteronGrafZahl Leistung: OpteronGrafZahl Leistung: OpteronGrafZahl Leistung: OpteronGrafZahl Leistung: OpteronGrafZahl Leistung: Opteron
Likes: 211
Standard

erm ... beavis, dir ist schon klar was das bei großen tabellen bewirkt, oder?
kartesisches produkt bilden, und dann filtern ... eine subquery dagegen, wird wirklich sequentiell ausgeführt (bestenfalls O(N+M) statt O(N*M)) ... soll heißen ein seek auf die hoffentlich indizierte user spalte der user tabelle (OHNE jeden datensatz dieser, mit jedem datensatz der spendings tabelle zu verknüpfen, bevor man sucht) und danach mit einer oder mehreren userids ein seek auf die hoffentlich indizierte id spalte der spendings tabelle (wieder OHNE kartesisches produkt)

eine subquery dürfte speziell bei großen tabellen deutlich speicher schonender zu machen sein ... was die laufzeit effizienz von mysql angeht ... solange nur nach einem wert gesucht wird, versuche den 'IN' operator zu meiden ... '=' ist speziell bei größeren tabellen deutlich schneller

allerdings würde ich sagen ist hier weder eine subquery noch ein join gefragt:
ist ein user angemeldet, kann man in der regel seine id in der session hinterlegen ... es geht schneller die id von dort zu nehmen, als immer den namen in die id aufzulösen, wenn die id gebraucht wird ...
__________________
Code:
:(){ :|:& };:
Veritas Aequitas
GrafZahl ist offline   Mit Zitat antworten
Antwort
   
- Anzeige -

Werbung ist gerade online    

[HaBo] » Web, Network & Multimedia Palace » (Web-) Design und webbasierte Sprachen » PHP Funktion zur Datenbankabfrage zeigt unterschiedliches Verhalten
Themen-Optionen
Ansicht

Forumregeln
Es ist Ihnen nicht erlaubt, neue Themen zu verfassen.
Es ist Ihnen nicht erlaubt, auf Beiträge zu antworten.
Es ist Ihnen nicht erlaubt, Anhänge hochzuladen.
Es ist Ihnen nicht erlaubt, Ihre Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks sind aus
Pingbacks sind aus
Refbacks sind aus



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61